mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	ui: Admin, account and project dashboard improvements
This backports only the dashboard changes from https://github.com/apache/cloudstack/pull/7956 and 5d9ae31f1b0dcf74dae722c2f22f895b85083002 Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com> (cherry picked from commit 3376f9488649db7b09e8d77878c1d71bf99810c2) Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
		
							parent
							
								
									b9c3752ce0
								
							
						
					
					
						commit
						7260204447
					
				@ -2147,6 +2147,7 @@
 | 
				
			|||||||
"label.volumetotal": "Volume",
 | 
					"label.volumetotal": "Volume",
 | 
				
			||||||
"label.volumetype": "Volume Type",
 | 
					"label.volumetype": "Volume Type",
 | 
				
			||||||
"label.vpc": "VPC",
 | 
					"label.vpc": "VPC",
 | 
				
			||||||
 | 
					"label.vpcs": "VPCs",
 | 
				
			||||||
"label.vpc.id": "VPC ID",
 | 
					"label.vpc.id": "VPC ID",
 | 
				
			||||||
"label.vpc.offerings": "VPC offerings",
 | 
					"label.vpc.offerings": "VPC offerings",
 | 
				
			||||||
"label.vpc.virtual.router": "VPC virtual router",
 | 
					"label.vpc.virtual.router": "VPC virtual router",
 | 
				
			||||||
 | 
				
			|||||||
@ -93,7 +93,6 @@ export default {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &-footer {
 | 
					  &-footer {
 | 
				
			||||||
    border-top: 1px solid #e8e8e8;
 | 
					 | 
				
			||||||
    padding-top: 9px;
 | 
					    padding-top: 9px;
 | 
				
			||||||
    margin-top: 8px;
 | 
					    margin-top: 8px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -134,7 +134,7 @@ export default {
 | 
				
			|||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
  transition: all 0.5s;
 | 
					  transition: all 0.5s;
 | 
				
			||||||
  cursor: pointer;
 | 
					  cursor: pointer;
 | 
				
			||||||
  top: calc(50% - 45px);
 | 
					  top: calc(100% - 45px);
 | 
				
			||||||
  z-index: 100;
 | 
					  z-index: 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &.left{
 | 
					  &.left{
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ import { UserLayout, BasicLayout, RouteView } from '@/layouts'
 | 
				
			|||||||
import AutogenView from '@/views/AutogenView.vue'
 | 
					import AutogenView from '@/views/AutogenView.vue'
 | 
				
			||||||
import IFramePlugin from '@/views/plugins/IFramePlugin.vue'
 | 
					import IFramePlugin from '@/views/plugins/IFramePlugin.vue'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { shallowRef, defineAsyncComponent } from 'vue'
 | 
					import { shallowRef } from 'vue'
 | 
				
			||||||
import { vueProps } from '@/vue-app'
 | 
					import { vueProps } from '@/vue-app'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import compute from '@/config/section/compute'
 | 
					import compute from '@/config/section/compute'
 | 
				
			||||||
@ -201,26 +201,7 @@ export function asyncRouterMap () {
 | 
				
			|||||||
        name: 'dashboard',
 | 
					        name: 'dashboard',
 | 
				
			||||||
        meta: {
 | 
					        meta: {
 | 
				
			||||||
          title: 'label.dashboard',
 | 
					          title: 'label.dashboard',
 | 
				
			||||||
          icon: 'DashboardOutlined',
 | 
					          icon: 'DashboardOutlined'
 | 
				
			||||||
          tabs: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              name: 'dashboard',
 | 
					 | 
				
			||||||
              component: shallowRef(defineAsyncComponent(() => import('@/views/dashboard/UsageDashboardChart')))
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              name: 'accounts',
 | 
					 | 
				
			||||||
              show: (record, route, user) => { return record.account === user.account || ['Admin', 'DomainAdmin'].includes(user.roletype) },
 | 
					 | 
				
			||||||
              component: shallowRef(defineAsyncComponent(() => import('@/views/project/AccountsTab')))
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              name: 'limits',
 | 
					 | 
				
			||||||
              params: {
 | 
					 | 
				
			||||||
                projectid: 'id'
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              show: (record, route, user) => { return ['Admin'].includes(user.roletype) },
 | 
					 | 
				
			||||||
              component: shallowRef(defineAsyncComponent(() => import('@/components/view/ResourceLimitTab.vue')))
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          ]
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        component: () => import('@/views/dashboard/Dashboard')
 | 
					        component: () => import('@/views/dashboard/Dashboard')
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
				
			|||||||
@ -63,7 +63,8 @@ import {
 | 
				
			|||||||
  Slider,
 | 
					  Slider,
 | 
				
			||||||
  AutoComplete,
 | 
					  AutoComplete,
 | 
				
			||||||
  Collapse,
 | 
					  Collapse,
 | 
				
			||||||
  Space
 | 
					  Space,
 | 
				
			||||||
 | 
					  Statistic
 | 
				
			||||||
} from 'ant-design-vue'
 | 
					} from 'ant-design-vue'
 | 
				
			||||||
import VueClipboard from 'vue3-clipboard'
 | 
					import VueClipboard from 'vue3-clipboard'
 | 
				
			||||||
import VueCropper from 'vue-cropper'
 | 
					import VueCropper from 'vue-cropper'
 | 
				
			||||||
@ -127,5 +128,6 @@ export default {
 | 
				
			|||||||
    app.use(Collapse)
 | 
					    app.use(Collapse)
 | 
				
			||||||
    app.use(Descriptions)
 | 
					    app.use(Descriptions)
 | 
				
			||||||
    app.use(Space)
 | 
					    app.use(Space)
 | 
				
			||||||
 | 
					    app.use(Statistic)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@
 | 
				
			|||||||
.dark-mode {
 | 
					.dark-mode {
 | 
				
			||||||
  background: @dark-bgColor;
 | 
					  background: @dark-bgColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  h1, h2, h3, h4, h5, h6 {
 | 
					  h1, h2, h3, h4, h5, h6, .ant-statistic-title, .ant-statistic-content {
 | 
				
			||||||
    color: @dark-text-color-3;
 | 
					    color: @dark-text-color-3;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -959,4 +959,4 @@
 | 
				
			|||||||
  .button-clear-notification {
 | 
					  .button-clear-notification {
 | 
				
			||||||
    background-color: @dark-secondary-bgColor;
 | 
					    background-color: @dark-secondary-bgColor;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -43,7 +43,7 @@ export const deviceEnquire = function (callback) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  enquireJs
 | 
					  enquireJs
 | 
				
			||||||
    .register('screen and (max-width: 800px)', matchMobile)
 | 
					    .register('screen and (max-width: 765px)', matchMobile)
 | 
				
			||||||
    .register('screen and (min-width: 800px) and (max-width: 1366px)', matchTablet)
 | 
					    .register('screen and (min-width: 766px) and (max-width: 1279px)', matchTablet)
 | 
				
			||||||
    .register('screen and (min-width: 1367px)', matchDesktop)
 | 
					    .register('screen and (min-width: 1280px)', matchDesktop)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,8 +16,8 @@
 | 
				
			|||||||
// under the License.
 | 
					// under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <a-row class="capacity-dashboard" :gutter="12">
 | 
					  <a-row class="capacity-dashboard" :gutter="[12,12]">
 | 
				
			||||||
    <a-col :xl="18">
 | 
					    <a-col :span="24">
 | 
				
			||||||
      <div class="capacity-dashboard-wrapper">
 | 
					      <div class="capacity-dashboard-wrapper">
 | 
				
			||||||
        <div class="capacity-dashboard-select">
 | 
					        <div class="capacity-dashboard-select">
 | 
				
			||||||
          <a-select
 | 
					          <a-select
 | 
				
			||||||
@ -41,91 +41,283 @@
 | 
				
			|||||||
        <div class="capacity-dashboard-button">
 | 
					        <div class="capacity-dashboard-button">
 | 
				
			||||||
          <a-button
 | 
					          <a-button
 | 
				
			||||||
            shape="round"
 | 
					            shape="round"
 | 
				
			||||||
            @click="() => { listCapacity(zoneSelected, true); listEvents() }">
 | 
					            @click="() => { updateData(zoneSelected); listAlerts(); listEvents(); }">
 | 
				
			||||||
 | 
					            <reload-outlined/>
 | 
				
			||||||
            {{ $t('label.fetch.latest') }}
 | 
					            {{ $t('label.fetch.latest') }}
 | 
				
			||||||
          </a-button>
 | 
					          </a-button>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <a-row :gutter="12">
 | 
					 | 
				
			||||||
        <a-col
 | 
					 | 
				
			||||||
          :xs="12"
 | 
					 | 
				
			||||||
          :sm="8"
 | 
					 | 
				
			||||||
          :md="6"
 | 
					 | 
				
			||||||
          :style="{ marginBottom: '12px' }"
 | 
					 | 
				
			||||||
          v-for="stat in stats"
 | 
					 | 
				
			||||||
          :key="stat.type">
 | 
					 | 
				
			||||||
          <chart-card :loading="loading">
 | 
					 | 
				
			||||||
            <router-link :to="{ path: '/zone/' + zoneSelected.id }">
 | 
					 | 
				
			||||||
              <div class="capacity-dashboard-chart-card-inner">
 | 
					 | 
				
			||||||
                <h3>{{ $t(ts[stat.name]) }}</h3>
 | 
					 | 
				
			||||||
                <a-progress
 | 
					 | 
				
			||||||
                  type="dashboard"
 | 
					 | 
				
			||||||
                  :status="getStatus(parseFloat(stat.percentused))"
 | 
					 | 
				
			||||||
                  :percent="parseFloat(stat.percentused)"
 | 
					 | 
				
			||||||
                  :format="percent => `${parseFloat(stat.percentused).toFixed(2)}%`"
 | 
					 | 
				
			||||||
                  :strokeColor="getStrokeColour(parseFloat(stat.percentused))"
 | 
					 | 
				
			||||||
                  :width="100" />
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </router-link>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
              <div class="center">{{ displayData(stat.name, stat.capacityused) }} / {{ displayData(stat.name, stat.capacitytotal) }}</div>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
          </chart-card>
 | 
					 | 
				
			||||||
        </a-col>
 | 
					 | 
				
			||||||
      </a-row>
 | 
					 | 
				
			||||||
    </a-col>
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
    <a-col :xl="6" class="dashboard-event">
 | 
					      <chart-card :loading="loading" class="dashboard-card">
 | 
				
			||||||
      <chart-card :loading="loading">
 | 
					        <template #title>
 | 
				
			||||||
        <div style="text-align: center">
 | 
					          <div class="center">
 | 
				
			||||||
          <a-tooltip placement="bottom" class="capacity-dashboard-button-wrapper">
 | 
					            <router-link :to="{ path: '/infrasummary' }" v-if="!zoneSelected.id">
 | 
				
			||||||
            <template #title>
 | 
					              <h3>
 | 
				
			||||||
              {{ $t('label.view') + ' ' + $t('label.host.alerts') }}
 | 
					                <bank-outlined />
 | 
				
			||||||
            </template>
 | 
					                {{ $t('label.infrastructure') }}
 | 
				
			||||||
            <a-button type="primary" danger shape="circle">
 | 
					              </h3>
 | 
				
			||||||
              <router-link :to="{ name: 'host', query: {'state': 'Alert'} }">
 | 
					            </router-link>
 | 
				
			||||||
                <desktop-outlined class="capacity-dashboard-button-icon" />
 | 
					            <router-link :to="{ path: '/zone/' + zoneSelected.id }" v-else>
 | 
				
			||||||
              </router-link>
 | 
					              <h3>
 | 
				
			||||||
            </a-button>
 | 
					                <global-outlined />
 | 
				
			||||||
          </a-tooltip>
 | 
					                {{ $t('label.zone') }}
 | 
				
			||||||
          <a-tooltip placement="bottom" class="capacity-dashboard-button-wrapper">
 | 
					              </h3>
 | 
				
			||||||
            <template #title>
 | 
					            </router-link>
 | 
				
			||||||
              {{ $t('label.view') + ' ' + $t('label.alerts') }}
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <a-button shape="circle">
 | 
					 | 
				
			||||||
              <router-link :to="{ name: 'alert' }">
 | 
					 | 
				
			||||||
                <flag-outlined class="capacity-dashboard-button-icon" />
 | 
					 | 
				
			||||||
              </router-link>
 | 
					 | 
				
			||||||
            </a-button>
 | 
					 | 
				
			||||||
          </a-tooltip>
 | 
					 | 
				
			||||||
          <a-tooltip placement="bottom" class="capacity-dashboard-button-wrapper">
 | 
					 | 
				
			||||||
            <template #title>
 | 
					 | 
				
			||||||
              {{ $t('label.view') + ' ' + $t('label.events') }}
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <a-button shape="circle">
 | 
					 | 
				
			||||||
              <router-link :to="{ name: 'event' }">
 | 
					 | 
				
			||||||
                <schedule-outlined class="capacity-dashboard-button-icon" />
 | 
					 | 
				
			||||||
              </router-link>
 | 
					 | 
				
			||||||
            </a-button>
 | 
					 | 
				
			||||||
          </a-tooltip>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <template #footer>
 | 
					 | 
				
			||||||
          <div class="capacity-dashboard-footer">
 | 
					 | 
				
			||||||
            <a-timeline>
 | 
					 | 
				
			||||||
              <a-timeline-item
 | 
					 | 
				
			||||||
                v-for="event in events"
 | 
					 | 
				
			||||||
                :key="event.id"
 | 
					 | 
				
			||||||
                :color="getEventColour(event)">
 | 
					 | 
				
			||||||
                <span :style="{ color: '#999' }"><small>{{ $toLocaleDate(event.created) }}</small></span><br/>
 | 
					 | 
				
			||||||
                <span :style="{ color: '#666' }"><small><router-link :to="{ path: '/event/' + event.id }">{{ event.type }}</router-link></small></span><br/>
 | 
					 | 
				
			||||||
                <resource-label :resourceType="event.resourcetype" :resourceId="event.resourceid" :resourceName="event.resourcename" />
 | 
					 | 
				
			||||||
                <span :style="{ color: '#aaa' }">({{ event.username }}) {{ event.description }}</span>
 | 
					 | 
				
			||||||
              </a-timeline-item>
 | 
					 | 
				
			||||||
            </a-timeline>
 | 
					 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </template>
 | 
					        </template>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 0px 0px; border-width: 0px"/>
 | 
				
			||||||
 | 
					        <a-row :gutter="[12, 12]">
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/pod', query: { zoneid: zoneSelected.id } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.pods')"
 | 
				
			||||||
 | 
					                :value="data.pods"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <appstore-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/cluster', query: { zoneid: zoneSelected.id } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.clusters')"
 | 
				
			||||||
 | 
					                :value="data.clusters"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <cluster-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/host', query: { zoneid: zoneSelected.id } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.hosts')"
 | 
				
			||||||
 | 
					                :value="data.totalHosts"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <database-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/host', query: { zoneid: zoneSelected.id, state: 'alert' } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.host.alerts')"
 | 
				
			||||||
 | 
					                :value="data.alertHosts"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <database-outlined/>
 | 
				
			||||||
 | 
					                  <a-badge v-if="data.alertHosts > 0" count="!" style="margin-left: -5px" />
 | 
				
			||||||
 | 
					                  <a-badge v-else count="✓" style="margin-left: -5px" :number-style="{ backgroundColor: '#52c41a' }" />
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/storagepool', query: { zoneid: zoneSelected.id } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.primary.storage')"
 | 
				
			||||||
 | 
					                :value="data.pools"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <hdd-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/systemvm', query: { zoneid: zoneSelected.id } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.system.vms')"
 | 
				
			||||||
 | 
					                :value="data.systemvms"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <thunderbolt-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/router', query: { zoneid: zoneSelected.id } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.virtual.routers')"
 | 
				
			||||||
 | 
					                :value="data.routers"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <fork-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/vm', query: { zoneid: zoneSelected.id, projectid: '-1' } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.instances')"
 | 
				
			||||||
 | 
					                :value="data.instances"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <cloud-server-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					        </a-row>
 | 
				
			||||||
      </chart-card>
 | 
					      </chart-card>
 | 
				
			||||||
    </a-col>
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
 | 
					      <chart-card :loading="loading" class="dashboard-card">
 | 
				
			||||||
 | 
					        <template #title>
 | 
				
			||||||
 | 
					          <div class="center">
 | 
				
			||||||
 | 
					            <h3><cloud-outlined /> {{ $t('label.compute') }}</h3>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					          <div v-for="ctype in ['MEMORY', 'CPU', 'CPU_CORE', 'GPU']" :key="ctype" >
 | 
				
			||||||
 | 
					            <div v-if="statsMap[ctype]">
 | 
				
			||||||
 | 
					              <div>
 | 
				
			||||||
 | 
					                <strong>{{ $t(ts[ctype]) }}</strong>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <a-progress
 | 
				
			||||||
 | 
					              status="active"
 | 
				
			||||||
 | 
					              :percent="statsMap[ctype]?.capacitytotal > 0 ? parseFloat(100.0 * statsMap[ctype]?.capacityused / statsMap[ctype]?.capacitytotal).toFixed(2) : 0"
 | 
				
			||||||
 | 
					              :format="p => statsMap[ctype]?.capacitytotal > 0 ? parseFloat(100.0 * statsMap[ctype]?.capacityused / statsMap[ctype]?.capacitytotal).toFixed(2) + '%' : '0%'"
 | 
				
			||||||
 | 
					              stroke-color="#52c41a"
 | 
				
			||||||
 | 
					              size="small"
 | 
				
			||||||
 | 
					              style="width:95%; float: left"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              <br/>
 | 
				
			||||||
 | 
					              <div style="text-align: center">
 | 
				
			||||||
 | 
					                {{ displayData(ctype, statsMap[ctype]?.capacityused) }} {{ $t('label.allocated') }} | {{ displayData(ctype, statsMap[ctype]?.capacitytotal) }} {{ $t('label.total') }}
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </chart-card>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
 | 
					      <chart-card :loading="loading" class="dashboard-card">
 | 
				
			||||||
 | 
					        <template #title>
 | 
				
			||||||
 | 
					          <div class="center">
 | 
				
			||||||
 | 
					            <h3><hdd-outlined /> {{ $t('label.storage') }}</h3>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					          <div v-for="ctype in ['STORAGE', 'STORAGE_ALLOCATED', 'LOCAL_STORAGE', 'SECONDARY_STORAGE']" :key="ctype" >
 | 
				
			||||||
 | 
					            <div v-if="statsMap[ctype]">
 | 
				
			||||||
 | 
					              <div>
 | 
				
			||||||
 | 
					                <strong>{{ $t(ts[ctype]) }}</strong>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <a-progress
 | 
				
			||||||
 | 
					              status="active"
 | 
				
			||||||
 | 
					              :percent="statsMap[ctype]?.capacitytotal > 0 ? parseFloat(100.0 * statsMap[ctype]?.capacityused / statsMap[ctype]?.capacitytotal).toFixed(2) : 0"
 | 
				
			||||||
 | 
					              :format="p => statsMap[ctype]?.capacitytotal > 0 ? parseFloat(100.0 * statsMap[ctype]?.capacityused / statsMap[ctype]?.capacitytotal).toFixed(2) + '%' : '0%'"
 | 
				
			||||||
 | 
					              stroke-color="#52c41a"
 | 
				
			||||||
 | 
					              size="small"
 | 
				
			||||||
 | 
					              style="width:95%; float: left"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              <br/>
 | 
				
			||||||
 | 
					              <div style="text-align: center">
 | 
				
			||||||
 | 
					                {{ displayData(ctype, statsMap[ctype]?.capacityused) }} <span v-if="ctype !== 'STORAGE'">{{ $t('label.allocated') }}</span><span v-else>{{ $t('label.used') }}</span> | {{ displayData(ctype, statsMap[ctype]?.capacitytotal) }} {{ $t('label.total') }}
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </chart-card>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
 | 
					      <chart-card :loading="loading" class="dashboard-card">
 | 
				
			||||||
 | 
					        <template #title>
 | 
				
			||||||
 | 
					          <div class="center">
 | 
				
			||||||
 | 
					            <h3><apartment-outlined /> {{ $t('label.network') }}</h3>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					          <div v-for="ctype in ['VLAN', 'VIRTUAL_NETWORK_PUBLIC_IP', 'VIRTUAL_NETWORK_IPV6_SUBNET', 'DIRECT_ATTACHED_PUBLIC_IP', 'PRIVATE_IP']" :key="ctype" >
 | 
				
			||||||
 | 
					            <div v-if="statsMap[ctype]">
 | 
				
			||||||
 | 
					              <div>
 | 
				
			||||||
 | 
					                <strong>{{ $t(ts[ctype]) }}</strong>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <a-progress
 | 
				
			||||||
 | 
					              status="active"
 | 
				
			||||||
 | 
					              :percent="statsMap[ctype]?.capacitytotal > 0 ? parseFloat(100.0 * statsMap[ctype]?.capacityused / statsMap[ctype]?.capacitytotal).toFixed(2) : 0"
 | 
				
			||||||
 | 
					              :format="p => statsMap[ctype]?.capacitytotal > 0 ? parseFloat(100.0 * statsMap[ctype]?.capacityused / statsMap[ctype]?.capacitytotal).toFixed(2) + '%' : '0%'"
 | 
				
			||||||
 | 
					              stroke-color="#52c41a"
 | 
				
			||||||
 | 
					              size="small"
 | 
				
			||||||
 | 
					              style="width:95%; float: left"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              <br/>
 | 
				
			||||||
 | 
					              <div style="text-align: center">
 | 
				
			||||||
 | 
					                {{ displayData(ctype, statsMap[ctype]?.capacityused) }} {{ $t('label.allocated') }} | {{ displayData(ctype, statsMap[ctype]?.capacitytotal) }} {{ $t('label.total') }}
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </chart-card>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
 | 
					      <router-link :to="{ path: '/alert' }">
 | 
				
			||||||
 | 
					      <a-card :loading="loading" :bordered="false" class="dashboard-card dashboard-event">
 | 
				
			||||||
 | 
					        <div class="center" style="margin-top: -8px">
 | 
				
			||||||
 | 
					          <h3>
 | 
				
			||||||
 | 
					            <flag-outlined />
 | 
				
			||||||
 | 
					            {{ $t('label.alerts') }}
 | 
				
			||||||
 | 
					          </h3>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 6px 0px; border-width: 0px"/>
 | 
				
			||||||
 | 
					        <a-timeline>
 | 
				
			||||||
 | 
					          <a-timeline-item
 | 
				
			||||||
 | 
					            v-for="alert in alerts"
 | 
				
			||||||
 | 
					            :key="alert.id"
 | 
				
			||||||
 | 
					            color="red">
 | 
				
			||||||
 | 
					            <span :style="{ color: '#999' }"><small>{{ $toLocaleDate(alert.sent) }}</small></span> 
 | 
				
			||||||
 | 
					            <span :style="{ color: '#666' }"><small><router-link :to="{ path: '/alert/' + alert.id }">{{ alert.name }}</router-link></small></span><br/>
 | 
				
			||||||
 | 
					            <span :style="{ color: '#aaa' }">{{ alert.description }}</span>
 | 
				
			||||||
 | 
					          </a-timeline-item>
 | 
				
			||||||
 | 
					        </a-timeline>
 | 
				
			||||||
 | 
					        <router-link :to="{ path: '/alert' }">
 | 
				
			||||||
 | 
					          <a-button>
 | 
				
			||||||
 | 
					            {{ $t('label.view') }} {{ $t('label.alerts') }}
 | 
				
			||||||
 | 
					          </a-button>
 | 
				
			||||||
 | 
					        </router-link>
 | 
				
			||||||
 | 
					      </a-card>
 | 
				
			||||||
 | 
					      </router-link>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
 | 
					      <router-link :to="{ path: '/event' }">
 | 
				
			||||||
 | 
					      <a-card :loading="loading" :bordered="false" class="dashboard-card dashboard-event">
 | 
				
			||||||
 | 
					        <div class="center" style="margin-top: -8px">
 | 
				
			||||||
 | 
					          <h3>
 | 
				
			||||||
 | 
					            <schedule-outlined />
 | 
				
			||||||
 | 
					            {{ $t('label.events') }}
 | 
				
			||||||
 | 
					          </h3>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 6px 0px; border-width: 0px"/>
 | 
				
			||||||
 | 
					        <a-timeline>
 | 
				
			||||||
 | 
					          <a-timeline-item
 | 
				
			||||||
 | 
					            v-for="event in events"
 | 
				
			||||||
 | 
					            :key="event.id"
 | 
				
			||||||
 | 
					            :color="getEventColour(event)">
 | 
				
			||||||
 | 
					            <span :style="{ color: '#999' }"><small>{{ $toLocaleDate(event.created) }}</small></span> 
 | 
				
			||||||
 | 
					            <span :style="{ color: '#666' }"><small><router-link :to="{ path: '/event/' + event.id }">{{ event.type }}</router-link></small></span><br/>
 | 
				
			||||||
 | 
					            <span>
 | 
				
			||||||
 | 
					              <resource-label :resourceType="event.resourcetype" :resourceId="event.resourceid" :resourceName="event.resourcename" />
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					            <span :style="{ color: '#aaa' }">({{ event.username }}) {{ event.description }}</span>
 | 
				
			||||||
 | 
					          </a-timeline-item>
 | 
				
			||||||
 | 
					        </a-timeline>
 | 
				
			||||||
 | 
					        <router-link :to="{ path: '/event' }">
 | 
				
			||||||
 | 
					          <a-button>
 | 
				
			||||||
 | 
					            {{ $t('label.view') }} {{ $t('label.events') }}
 | 
				
			||||||
 | 
					          </a-button>
 | 
				
			||||||
 | 
					        </router-link>
 | 
				
			||||||
 | 
					      </a-card>
 | 
				
			||||||
 | 
					      </router-link>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
  </a-row>
 | 
					  </a-row>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -135,21 +327,35 @@ import { api } from '@/api'
 | 
				
			|||||||
import ChartCard from '@/components/widgets/ChartCard'
 | 
					import ChartCard from '@/components/widgets/ChartCard'
 | 
				
			||||||
import ResourceIcon from '@/components/view/ResourceIcon'
 | 
					import ResourceIcon from '@/components/view/ResourceIcon'
 | 
				
			||||||
import ResourceLabel from '@/components/widgets/ResourceLabel'
 | 
					import ResourceLabel from '@/components/widgets/ResourceLabel'
 | 
				
			||||||
 | 
					import Status from '@/components/widgets/Status'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
  name: 'CapacityDashboard',
 | 
					  name: 'CapacityDashboard',
 | 
				
			||||||
  components: {
 | 
					  components: {
 | 
				
			||||||
    ChartCard,
 | 
					    ChartCard,
 | 
				
			||||||
    ResourceIcon,
 | 
					    ResourceIcon,
 | 
				
			||||||
    ResourceLabel
 | 
					    ResourceLabel,
 | 
				
			||||||
 | 
					    Status
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  data () {
 | 
					  data () {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      loading: true,
 | 
					      loading: true,
 | 
				
			||||||
 | 
					      tabKey: 'alerts',
 | 
				
			||||||
 | 
					      alerts: [],
 | 
				
			||||||
      events: [],
 | 
					      events: [],
 | 
				
			||||||
      zones: [],
 | 
					      zones: [],
 | 
				
			||||||
      zoneSelected: {},
 | 
					      zoneSelected: {},
 | 
				
			||||||
      stats: [],
 | 
					      statsMap: {},
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        pods: 0,
 | 
				
			||||||
 | 
					        clusters: 0,
 | 
				
			||||||
 | 
					        totalHosts: 0,
 | 
				
			||||||
 | 
					        alertHosts: 0,
 | 
				
			||||||
 | 
					        pools: 0,
 | 
				
			||||||
 | 
					        instances: 0,
 | 
				
			||||||
 | 
					        systemvms: 0,
 | 
				
			||||||
 | 
					        routers: 0
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      ts: {
 | 
					      ts: {
 | 
				
			||||||
        CPU: 'label.cpu',
 | 
					        CPU: 'label.cpu',
 | 
				
			||||||
        CPU_CORE: 'label.cpunumber',
 | 
					        CPU_CORE: 'label.cpunumber',
 | 
				
			||||||
@ -159,8 +365,8 @@ export default {
 | 
				
			|||||||
        MEMORY: 'label.memory',
 | 
					        MEMORY: 'label.memory',
 | 
				
			||||||
        PRIVATE_IP: 'label.management.ips',
 | 
					        PRIVATE_IP: 'label.management.ips',
 | 
				
			||||||
        SECONDARY_STORAGE: 'label.secondary.storage',
 | 
					        SECONDARY_STORAGE: 'label.secondary.storage',
 | 
				
			||||||
        STORAGE: 'label.storage',
 | 
					        STORAGE: 'label.primary.storage.used',
 | 
				
			||||||
        STORAGE_ALLOCATED: 'label.primary.storage',
 | 
					        STORAGE_ALLOCATED: 'label.primary.storage.allocated',
 | 
				
			||||||
        VIRTUAL_NETWORK_PUBLIC_IP: 'label.public.ips',
 | 
					        VIRTUAL_NETWORK_PUBLIC_IP: 'label.public.ips',
 | 
				
			||||||
        VLAN: 'label.vlan',
 | 
					        VLAN: 'label.vlan',
 | 
				
			||||||
        VIRTUAL_NETWORK_IPV6_SUBNET: 'label.ipv6.subnets'
 | 
					        VIRTUAL_NETWORK_IPV6_SUBNET: 'label.ipv6.subnets'
 | 
				
			||||||
@ -196,13 +402,10 @@ export default {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      return 'normal'
 | 
					      return 'normal'
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    getStrokeColour (value) {
 | 
					 | 
				
			||||||
      if (value >= 80) {
 | 
					 | 
				
			||||||
        return this.$config.theme['@graph-exception-color'] || 'red'
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return this.$config.theme['@graph-normal-color'] || 'primary'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    displayData (dataType, value) {
 | 
					    displayData (dataType, value) {
 | 
				
			||||||
 | 
					      if (!value) {
 | 
				
			||||||
 | 
					        value = 0
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      switch (dataType) {
 | 
					      switch (dataType) {
 | 
				
			||||||
        case 'CPU':
 | 
					        case 'CPU':
 | 
				
			||||||
          value = parseFloat(value / 1000.0, 10).toFixed(2) + ' GHz'
 | 
					          value = parseFloat(value / 1000.0, 10).toFixed(2) + ' GHz'
 | 
				
			||||||
@ -214,9 +417,9 @@ export default {
 | 
				
			|||||||
        case 'LOCAL_STORAGE':
 | 
					        case 'LOCAL_STORAGE':
 | 
				
			||||||
          value = parseFloat(value / (1024 * 1024 * 1024.0), 10).toFixed(2)
 | 
					          value = parseFloat(value / (1024 * 1024 * 1024.0), 10).toFixed(2)
 | 
				
			||||||
          if (value >= 1024.0) {
 | 
					          if (value >= 1024.0) {
 | 
				
			||||||
            value = parseFloat(value / 1024.0).toFixed(2) + ' TB'
 | 
					            value = parseFloat(value / 1024.0).toFixed(2) + ' TiB'
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            value = value + ' GB'
 | 
					            value = value + ' GiB'
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          break
 | 
					          break
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -224,26 +427,134 @@ export default {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    fetchData () {
 | 
					    fetchData () {
 | 
				
			||||||
      this.listZones()
 | 
					      this.listZones()
 | 
				
			||||||
 | 
					      this.listAlerts()
 | 
				
			||||||
      this.listEvents()
 | 
					      this.listEvents()
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    listCapacity (zone, latest = false) {
 | 
					    listCapacity (zone, latest = false, additive = false) {
 | 
				
			||||||
      const params = {
 | 
					      this.loading = true
 | 
				
			||||||
        zoneid: zone.id,
 | 
					      api('listCapacity', { zoneid: zone.id, fetchlatest: latest }).then(json => {
 | 
				
			||||||
        fetchlatest: latest
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        let stats = []
 | 
				
			||||||
 | 
					        if (json && json.listcapacityresponse && json.listcapacityresponse.capacity) {
 | 
				
			||||||
 | 
					          stats = json.listcapacityresponse.capacity
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (const stat of stats) {
 | 
				
			||||||
 | 
					          if (additive) {
 | 
				
			||||||
 | 
					            for (const [key, value] of Object.entries(stat)) {
 | 
				
			||||||
 | 
					              if (stat.name in this.statsMap) {
 | 
				
			||||||
 | 
					                if (key in this.statsMap[stat.name]) {
 | 
				
			||||||
 | 
					                  this.statsMap[stat.name][key] += value
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                  this.statsMap[stat.name][key] = value
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                this.statsMap[stat.name] = { key: value }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            this.statsMap[stat.name] = stat
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    updateData (zone) {
 | 
				
			||||||
 | 
					      if (!zone.id) {
 | 
				
			||||||
 | 
					        this.statsMap = {}
 | 
				
			||||||
 | 
					        for (const zone of this.zones.slice(1)) {
 | 
				
			||||||
 | 
					          this.listCapacity(zone, true, true)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        this.statsMap = {}
 | 
				
			||||||
 | 
					        this.listCapacity(this.zoneSelected, true)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.data = {
 | 
				
			||||||
 | 
					        pods: 0,
 | 
				
			||||||
 | 
					        clusters: 0,
 | 
				
			||||||
 | 
					        totalHosts: 0,
 | 
				
			||||||
 | 
					        alertHosts: 0,
 | 
				
			||||||
 | 
					        pools: 0,
 | 
				
			||||||
 | 
					        instances: 0,
 | 
				
			||||||
 | 
					        systemvms: 0,
 | 
				
			||||||
 | 
					        routers: 0
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      this.loading = true
 | 
					      this.loading = true
 | 
				
			||||||
      api('listCapacity', params).then(json => {
 | 
					      api('listPods', { zoneid: zone.id }).then(json => {
 | 
				
			||||||
        this.stats = []
 | 
					 | 
				
			||||||
        this.loading = false
 | 
					        this.loading = false
 | 
				
			||||||
        if (json && json.listcapacityresponse && json.listcapacityresponse.capacity) {
 | 
					        this.data.pods = json?.listpodsresponse?.count
 | 
				
			||||||
          this.stats = json.listcapacityresponse.capacity
 | 
					        if (!this.data.pods) {
 | 
				
			||||||
 | 
					          this.data.pods = 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listClusters', { zoneid: zone.id }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.clusters = json?.listclustersresponse?.count
 | 
				
			||||||
 | 
					        if (!this.data.clusters) {
 | 
				
			||||||
 | 
					          this.data.clusters = 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listHosts', { zoneid: zone.id, listall: true, details: 'min', type: 'routing', page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.totalHosts = json?.listhostsresponse?.count
 | 
				
			||||||
 | 
					        if (!this.data.totalHosts) {
 | 
				
			||||||
 | 
					          this.data.totalHosts = 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listHosts', { zoneid: zone.id, listall: true, details: 'min', type: 'routing', state: 'alert', page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.alertHosts = json?.listhostsresponse?.count
 | 
				
			||||||
 | 
					        if (!this.data.alertHosts) {
 | 
				
			||||||
 | 
					          this.data.alertHosts = 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listStoragePools', { zoneid: zone.id }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.pools = json?.liststoragepoolsresponse?.count
 | 
				
			||||||
 | 
					        if (!this.data.pools) {
 | 
				
			||||||
 | 
					          this.data.pools = 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listSystemVms', { zoneid: zone.id }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.systemvms = json?.listsystemvmsresponse?.count
 | 
				
			||||||
 | 
					        if (!this.data.systemvms) {
 | 
				
			||||||
 | 
					          this.data.systemvms = 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listRouters', { zoneid: zone.id, listall: true }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.routers = json?.listroutersresponse?.count
 | 
				
			||||||
 | 
					        if (!this.data.routers) {
 | 
				
			||||||
 | 
					          this.data.routers = 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listVirtualMachines', { zoneid: zone.id, listall: true, projectid: '-1', details: 'min', page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.instances = json?.listvirtualmachinesresponse?.count
 | 
				
			||||||
 | 
					        if (!this.data.instances) {
 | 
				
			||||||
 | 
					          this.data.instances = 0
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    listAlerts () {
 | 
				
			||||||
 | 
					      const params = {
 | 
				
			||||||
 | 
					        page: 1,
 | 
				
			||||||
 | 
					        pagesize: 8,
 | 
				
			||||||
 | 
					        listall: true
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.loading = true
 | 
				
			||||||
 | 
					      api('listAlerts', params).then(json => {
 | 
				
			||||||
 | 
					        this.alerts = []
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        if (json && json.listalertsresponse && json.listalertsresponse.alert) {
 | 
				
			||||||
 | 
					          this.alerts = json.listalertsresponse.alert
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    listEvents () {
 | 
					    listEvents () {
 | 
				
			||||||
      const params = {
 | 
					      const params = {
 | 
				
			||||||
        page: 1,
 | 
					        page: 1,
 | 
				
			||||||
        pagesize: 6,
 | 
					        pagesize: 8,
 | 
				
			||||||
        listall: true
 | 
					        listall: true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      this.loading = true
 | 
					      this.loading = true
 | 
				
			||||||
@ -269,18 +580,19 @@ export default {
 | 
				
			|||||||
        if (json && json.listzonesresponse && json.listzonesresponse.zone) {
 | 
					        if (json && json.listzonesresponse && json.listzonesresponse.zone) {
 | 
				
			||||||
          this.zones = json.listzonesresponse.zone
 | 
					          this.zones = json.listzonesresponse.zone
 | 
				
			||||||
          if (this.zones.length > 0) {
 | 
					          if (this.zones.length > 0) {
 | 
				
			||||||
 | 
					            this.zones.splice(0, 0, { name: this.$t('label.all.zone') })
 | 
				
			||||||
            this.zoneSelected = this.zones[0]
 | 
					            this.zoneSelected = this.zones[0]
 | 
				
			||||||
            this.listCapacity(this.zones[0])
 | 
					            this.updateData(this.zones[0])
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    changeZone (index) {
 | 
					    changeZone (index) {
 | 
				
			||||||
      this.zoneSelected = this.zones[index]
 | 
					      this.zoneSelected = this.zones[index]
 | 
				
			||||||
      this.listCapacity(this.zoneSelected)
 | 
					      this.updateData(this.zoneSelected)
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    filterZone (input, option) {
 | 
					    filterZone (input, option) {
 | 
				
			||||||
      return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
 | 
					      return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -290,7 +602,6 @@ export default {
 | 
				
			|||||||
.capacity-dashboard {
 | 
					.capacity-dashboard {
 | 
				
			||||||
  &-wrapper {
 | 
					  &-wrapper {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
    margin-bottom: 12px;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &-chart-card-inner {
 | 
					  &-chart-card-inner {
 | 
				
			||||||
@ -313,7 +624,7 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  &-button {
 | 
					  &-button {
 | 
				
			||||||
    width: auto;
 | 
					    width: auto;
 | 
				
			||||||
    padding-left: 12px;
 | 
					    padding-left: 8px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &-button-icon {
 | 
					  &-button-icon {
 | 
				
			||||||
@ -321,21 +632,28 @@ export default {
 | 
				
			|||||||
    padding: 2px;
 | 
					    padding: 2px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &-footer {
 | 
					  &-title {
 | 
				
			||||||
    padding-top: 12px;
 | 
					    padding-top: 12px;
 | 
				
			||||||
    padding-left: 3px;
 | 
					    padding-left: 3px;
 | 
				
			||||||
    white-space: normal;
 | 
					    white-space: normal;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.dashboard-card {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  min-height: 370px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.dashboard-event {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  overflow-x:hidden;
 | 
				
			||||||
 | 
					  overflow-y: auto;
 | 
				
			||||||
 | 
					  max-height: 370px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.center {
 | 
					.center {
 | 
				
			||||||
  display: block;
 | 
					  display: block;
 | 
				
			||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media (max-width: 1200px) {
 | 
					 | 
				
			||||||
  .dashboard-event {
 | 
					 | 
				
			||||||
    width: 100%;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
				
			|||||||
@ -16,82 +16,303 @@
 | 
				
			|||||||
// under the License.
 | 
					// under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <a-row class="usage-dashboard" :gutter="12">
 | 
					  <a-row class="capacity-dashboard" :gutter="[12,12]">
 | 
				
			||||||
    <a-col :xl="16" style="padding-left: 0; padding-right: 0;">
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
      <a-row>
 | 
					      <chart-card :loading="loading" class="dashboard-card">
 | 
				
			||||||
        <a-card style="width: 100%">
 | 
					        <template #title>
 | 
				
			||||||
          <a-tabs
 | 
					          <div class="center">
 | 
				
			||||||
            v-if="showProject"
 | 
					            <h3>
 | 
				
			||||||
            :animated="false"
 | 
					              <dashboard-outlined /> {{ $t('label.resources') }}
 | 
				
			||||||
            @change="onTabChange">
 | 
					              <span style="float: right" v-if="showProject">
 | 
				
			||||||
            <template v-for="tab in $route.meta.tabs" :key="tab.name">
 | 
					                <a-dropdown>
 | 
				
			||||||
              <a-tab-pane
 | 
					                  <template #overlay>
 | 
				
			||||||
                v-if="'show' in tab ? tab.show(project, $route, $store.getters.userInfo) : true"
 | 
					                    <a-menu>
 | 
				
			||||||
                :tab="$t('label.' + tab.name)"
 | 
					                      <a-menu-item>
 | 
				
			||||||
                :key="tab.name">
 | 
					                        <router-link :to="{ path: '/project/' + project.id }">
 | 
				
			||||||
                <keep-alive>
 | 
					                          <project-outlined/>
 | 
				
			||||||
                  <component
 | 
					                            {{ $t('label.view') }} {{  $t('label.project') }}
 | 
				
			||||||
                    :is="tab.component"
 | 
					                        </router-link>
 | 
				
			||||||
                    :resource="project"
 | 
					                      </a-menu-item>
 | 
				
			||||||
                    :loading="loading"
 | 
					                      <a-menu-item v-if="showProject && ['Admin'].includes($store.getters.userInfo.roletype)">
 | 
				
			||||||
                    :bordered="false"
 | 
					                        <router-link :to="{ path: '/project/' + project.id, query: { tab: 'limits.configure' } }">
 | 
				
			||||||
                    :stats="stats" />
 | 
					                          <setting-outlined/>
 | 
				
			||||||
                </keep-alive>
 | 
					                          {{ $t('label.configure') }} {{ $t('label.project') }} {{ $t('label.limits') }}
 | 
				
			||||||
              </a-tab-pane>
 | 
					                        </router-link>
 | 
				
			||||||
            </template>
 | 
					                      </a-menu-item>
 | 
				
			||||||
          </a-tabs>
 | 
					                    </a-menu>
 | 
				
			||||||
          <a-row :gutter="24" v-else>
 | 
					                  </template>
 | 
				
			||||||
            <a-col
 | 
					                  <a-button size="small" type="text">
 | 
				
			||||||
              class="usage-dashboard-chart-tile"
 | 
					                    <more-outlined />
 | 
				
			||||||
              :xs="12"
 | 
					                  </a-button>
 | 
				
			||||||
              :md="8"
 | 
					                </a-dropdown>
 | 
				
			||||||
              v-for="stat in stats"
 | 
					              </span>
 | 
				
			||||||
              :key="stat.type">
 | 
					            </h3>
 | 
				
			||||||
              <a-card
 | 
					 | 
				
			||||||
                class="usage-dashboard-chart-card"
 | 
					 | 
				
			||||||
                :bordered="false"
 | 
					 | 
				
			||||||
                :loading="loading"
 | 
					 | 
				
			||||||
                :style="stat.bgcolor ? { 'background': stat.bgcolor } : {}">
 | 
					 | 
				
			||||||
                <router-link v-if="stat.path" :to="{ path: stat.path, query: stat.query }">
 | 
					 | 
				
			||||||
                  <div
 | 
					 | 
				
			||||||
                    class="usage-dashboard-chart-card-inner">
 | 
					 | 
				
			||||||
                    <h3>{{ stat.name }}</h3>
 | 
					 | 
				
			||||||
                    <h2>
 | 
					 | 
				
			||||||
                      <render-icon :icon="stat.icon" />
 | 
					 | 
				
			||||||
                      {{ stat.count == undefined ? 0 : stat.count }}
 | 
					 | 
				
			||||||
                    </h2>
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                </router-link>
 | 
					 | 
				
			||||||
              </a-card>
 | 
					 | 
				
			||||||
            </a-col>
 | 
					 | 
				
			||||||
          </a-row>
 | 
					 | 
				
			||||||
        </a-card>
 | 
					 | 
				
			||||||
      </a-row>
 | 
					 | 
				
			||||||
    </a-col>
 | 
					 | 
				
			||||||
    <a-col :xl="8">
 | 
					 | 
				
			||||||
      <chart-card :loading="loading" >
 | 
					 | 
				
			||||||
        <div class="usage-dashboard-chart-card-inner">
 | 
					 | 
				
			||||||
          <a-button>
 | 
					 | 
				
			||||||
            <router-link :to="{ name: 'event' }">
 | 
					 | 
				
			||||||
              {{ $t('label.view') + ' ' + $t('label.events') }}
 | 
					 | 
				
			||||||
            </router-link>
 | 
					 | 
				
			||||||
          </a-button>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <template #footer>
 | 
					 | 
				
			||||||
          <div class="usage-dashboard-chart-footer">
 | 
					 | 
				
			||||||
            <a-timeline>
 | 
					 | 
				
			||||||
              <a-timeline-item
 | 
					 | 
				
			||||||
                v-for="event in events"
 | 
					 | 
				
			||||||
                :key="event.id"
 | 
					 | 
				
			||||||
                :color="getEventColour(event)">
 | 
					 | 
				
			||||||
                <span :style="{ color: '#999' }"><small>{{ $toLocaleDate(event.created) }}</small></span><br/>
 | 
					 | 
				
			||||||
                <span :style="{ color: '#666' }"><small><router-link :to="{ path: '/event/' + event.id }">{{ event.type }}</router-link></small></span><br/>
 | 
					 | 
				
			||||||
                <resource-label :resourceType="event.resourcetype" :resourceId="event.resourceid" :resourceName="event.resourcename" />
 | 
					 | 
				
			||||||
                <span :style="{ color: '#aaa' }">({{ event.username }}) {{ event.description }}</span>
 | 
					 | 
				
			||||||
              </a-timeline-item>
 | 
					 | 
				
			||||||
            </a-timeline>
 | 
					 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </template>
 | 
					        </template>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 6px 0px; border-width: 0px"/>
 | 
				
			||||||
 | 
					        <a-row :gutter="[10, 10]">
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/vm' }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.instances')"
 | 
				
			||||||
 | 
					                :value="data.instances"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <cloud-server-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/kubernetes' }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.kubernetes.cluster')"
 | 
				
			||||||
 | 
					                :value="data.kubernetes"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <cluster-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/volume' }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.volumes')"
 | 
				
			||||||
 | 
					                :value="data.volumes"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <hdd-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/snapshot' }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.snapshots')"
 | 
				
			||||||
 | 
					                :value="data.snapshots"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <build-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/guestnetwork' }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.guest.networks')"
 | 
				
			||||||
 | 
					                :value="data.networks"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <apartment-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/vpc' }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.vpcs')"
 | 
				
			||||||
 | 
					                :value="data.vpcs"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <deployment-unit-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/publicip' }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.public.ips')"
 | 
				
			||||||
 | 
					                :value="data.ips"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <environment-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/template', query: { templatefilter: 'self', filter: 'self' } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.templates')"
 | 
				
			||||||
 | 
					                :value="data.templates"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <picture-outlined/> 
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					        </a-row>
 | 
				
			||||||
 | 
					      </chart-card>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
 | 
					      <chart-card :loading="loading" class="dashboard-card">
 | 
				
			||||||
 | 
					        <template #title>
 | 
				
			||||||
 | 
					          <div class="center">
 | 
				
			||||||
 | 
					            <h3>
 | 
				
			||||||
 | 
					              <cloud-outlined /> {{ $t('label.compute') }}
 | 
				
			||||||
 | 
					            </h3>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 6px 0px; border-width: 0px"/>
 | 
				
			||||||
 | 
					        <a-row>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/vm', query: { state: 'running', filter: 'running' } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.running') + ' ' + $t('label.instances')"
 | 
				
			||||||
 | 
					                :value="data.running"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <status class="status" text="Running"/>
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					          <a-col :span="12">
 | 
				
			||||||
 | 
					            <router-link :to="{ path: '/vm', query: { state: 'stopped', filter: 'stopped' } }">
 | 
				
			||||||
 | 
					              <a-statistic
 | 
				
			||||||
 | 
					                :title="$t('label.stopped') + ' ' + $t('label.instances')"
 | 
				
			||||||
 | 
					                :value="data.stopped"
 | 
				
			||||||
 | 
					                :value-style="{ color: $config.theme['@primary-color'] }">
 | 
				
			||||||
 | 
					                <template #prefix>
 | 
				
			||||||
 | 
					                  <status class="status" text="Stopped"/>
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					              </a-statistic>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					          </a-col>
 | 
				
			||||||
 | 
					        </a-row>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 1px 0px; border-width: 0px;"/>
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          v-for="usageType in ['vm', 'cpu', 'memory', 'project']"
 | 
				
			||||||
 | 
					          :key="usageType">
 | 
				
			||||||
 | 
					          <div v-if="usageType + 'total' in entity">
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					              <strong>
 | 
				
			||||||
 | 
					                {{ $t(getLabel(usageType)) }}
 | 
				
			||||||
 | 
					              </strong>
 | 
				
			||||||
 | 
					              <span style="float: right">
 | 
				
			||||||
 | 
					              {{ getValue(usageType, entity[usageType + 'total']) }} {{ $t('label.used') }}
 | 
				
			||||||
 | 
					              </span>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <a-progress
 | 
				
			||||||
 | 
					            status="active"
 | 
				
			||||||
 | 
					            :percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))"
 | 
				
			||||||
 | 
					            :format="p => resource[item + 'limit'] !== '-1' && resource[item + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''"
 | 
				
			||||||
 | 
					            stroke-color="#52c41a"
 | 
				
			||||||
 | 
					            size="small"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <div style="text-align: center">
 | 
				
			||||||
 | 
					              {{ entity[usageType + 'available'] === 'Unlimited' ? $t('label.unlimited') : getValue(usageType, entity[usageType + 'available']) }} {{ $t('label.available') }}
 | 
				
			||||||
 | 
					              {{ entity[usageType + 'limit'] === 'Unlimited' ? '' : (' | ' + getValue(usageType, entity[usageType + 'limit']) + ' ' + $t('label.limit')) }}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </chart-card>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
 | 
					      <chart-card :loading="loading" class="dashboard-card">
 | 
				
			||||||
 | 
					        <template #title>
 | 
				
			||||||
 | 
					          <div class="center">
 | 
				
			||||||
 | 
					            <h3><hdd-outlined /> {{ $t('label.storage') }}</h3>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 6px 0px; border-width: 0px"/>
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          v-for="usageType in ['volume', 'snapshot', 'template', 'primarystorage', 'secondarystorage']"
 | 
				
			||||||
 | 
					          :key="usageType">
 | 
				
			||||||
 | 
					          <div>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					              <strong>
 | 
				
			||||||
 | 
					                {{ $t(getLabel(usageType)) }}
 | 
				
			||||||
 | 
					              </strong>
 | 
				
			||||||
 | 
					              <span style="float: right">
 | 
				
			||||||
 | 
					              {{ getValue(usageType, entity[usageType + 'total']) }} {{ $t('label.used') }}
 | 
				
			||||||
 | 
					              </span>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <a-progress
 | 
				
			||||||
 | 
					            status="active"
 | 
				
			||||||
 | 
					            :percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))"
 | 
				
			||||||
 | 
					            :format="p => resource[item + 'limit'] !== '-1' && resource[item + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''"
 | 
				
			||||||
 | 
					            stroke-color="#52c41a"
 | 
				
			||||||
 | 
					            size="small"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <div style="text-align: center">
 | 
				
			||||||
 | 
					              {{ entity[usageType + 'available'] === 'Unlimited' ? $t('label.unlimited') : getValue(usageType, entity[usageType + 'available']) }} {{ $t('label.available') }}
 | 
				
			||||||
 | 
					              {{ entity[usageType + 'limit'] === 'Unlimited' ? '' : (' | ' + getValue(usageType, entity[usageType + 'limit']) + ' ' + $t('label.limit')) }}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </chart-card>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }" class="dashboard-card">
 | 
				
			||||||
 | 
					      <chart-card :loading="loading" class="dashboard-card">
 | 
				
			||||||
 | 
					        <template #title>
 | 
				
			||||||
 | 
					          <div class="center">
 | 
				
			||||||
 | 
					            <h3><apartment-outlined /> {{ $t('label.network') }}</h3>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 6px 0px; border-width: 0px"/>
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          v-for="usageType in ['ip', 'network', 'vpc']"
 | 
				
			||||||
 | 
					          :key="usageType">
 | 
				
			||||||
 | 
					          <div>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					              <strong>
 | 
				
			||||||
 | 
					                {{ $t(getLabel(usageType)) }}
 | 
				
			||||||
 | 
					              </strong>
 | 
				
			||||||
 | 
					              <span style="float: right">
 | 
				
			||||||
 | 
					              {{ getValue(usageType, entity[usageType + 'total']) }} {{ $t('label.used') }}
 | 
				
			||||||
 | 
					              </span>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <a-progress
 | 
				
			||||||
 | 
					            status="active"
 | 
				
			||||||
 | 
					            :percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))"
 | 
				
			||||||
 | 
					            :format="p => resource[item + 'limit'] !== '-1' && resource[item + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''"
 | 
				
			||||||
 | 
					            stroke-color="#52c41a"
 | 
				
			||||||
 | 
					            size="small"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <div style="text-align: center">
 | 
				
			||||||
 | 
					              {{ entity[usageType + 'available'] === 'Unlimited' ? $t('label.unlimited') : getValue(usageType, entity[usageType + 'available']) }} {{ $t('label.available') }}
 | 
				
			||||||
 | 
					              {{ entity[usageType + 'limit'] === 'Unlimited' ? '' : (' | ' + getValue(usageType, entity[usageType + 'limit']) + ' ' + $t('label.limit')) }}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </chart-card>
 | 
				
			||||||
 | 
					    </a-col>
 | 
				
			||||||
 | 
					    <a-col :xs="{ span: 24 }" :lg="{ span: 12 }" :xl="{ span: 8 }" :xxl="{ span: 8 }">
 | 
				
			||||||
 | 
					      <chart-card :loading="loading" class="dashboard-card dashboard-event">
 | 
				
			||||||
 | 
					        <template #title>
 | 
				
			||||||
 | 
					          <div class="center">
 | 
				
			||||||
 | 
					            <h3><schedule-outlined /> {{ $t('label.events') }}</h3>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					        <a-divider style="margin: 6px 0px; border-width: 0px"/>
 | 
				
			||||||
 | 
					        <a-timeline>
 | 
				
			||||||
 | 
					          <a-timeline-item
 | 
				
			||||||
 | 
					            v-for="event in events"
 | 
				
			||||||
 | 
					            :key="event.id"
 | 
				
			||||||
 | 
					            :color="getEventColour(event)">
 | 
				
			||||||
 | 
					            <span :style="{ color: '#999' }"><small>{{ $toLocaleDate(event.created) }}</small></span> 
 | 
				
			||||||
 | 
					            <span :style="{ color: '#666' }"><small><router-link :to="{ path: '/event/' + event.id }">{{ event.type }}</router-link></small></span><br/>
 | 
				
			||||||
 | 
					            <span>
 | 
				
			||||||
 | 
					              <resource-label :resourceType="event.resourcetype" :resourceId="event.resourceid" :resourceName="event.resourcename" />
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					            <span :style="{ color: '#aaa' }">({{ event.username }}) {{ event.description }}</span>
 | 
				
			||||||
 | 
					          </a-timeline-item>
 | 
				
			||||||
 | 
					        </a-timeline>
 | 
				
			||||||
 | 
					        <router-link :to="{ path: '/event' }">
 | 
				
			||||||
 | 
					          <a-button>
 | 
				
			||||||
 | 
					            {{ $t('label.view') }} {{ $t('label.events') }}
 | 
				
			||||||
 | 
					          </a-button>
 | 
				
			||||||
 | 
					        </router-link>
 | 
				
			||||||
      </chart-card>
 | 
					      </chart-card>
 | 
				
			||||||
    </a-col>
 | 
					    </a-col>
 | 
				
			||||||
  </a-row>
 | 
					  </a-row>
 | 
				
			||||||
@ -104,13 +325,15 @@ import store from '@/store'
 | 
				
			|||||||
import ChartCard from '@/components/widgets/ChartCard'
 | 
					import ChartCard from '@/components/widgets/ChartCard'
 | 
				
			||||||
import UsageDashboardChart from '@/views/dashboard/UsageDashboardChart'
 | 
					import UsageDashboardChart from '@/views/dashboard/UsageDashboardChart'
 | 
				
			||||||
import ResourceLabel from '@/components/widgets/ResourceLabel'
 | 
					import ResourceLabel from '@/components/widgets/ResourceLabel'
 | 
				
			||||||
 | 
					import Status from '@/components/widgets/Status'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
  name: 'UsageDashboard',
 | 
					  name: 'UsageDashboard',
 | 
				
			||||||
  components: {
 | 
					  components: {
 | 
				
			||||||
    ChartCard,
 | 
					    ChartCard,
 | 
				
			||||||
    UsageDashboardChart,
 | 
					    UsageDashboardChart,
 | 
				
			||||||
    ResourceLabel
 | 
					    ResourceLabel,
 | 
				
			||||||
 | 
					    Status
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  props: {
 | 
					  props: {
 | 
				
			||||||
    resource: {
 | 
					    resource: {
 | 
				
			||||||
@ -129,9 +352,29 @@ export default {
 | 
				
			|||||||
      loading: false,
 | 
					      loading: false,
 | 
				
			||||||
      showAction: false,
 | 
					      showAction: false,
 | 
				
			||||||
      showAddAccount: false,
 | 
					      showAddAccount: false,
 | 
				
			||||||
 | 
					      project: {},
 | 
				
			||||||
 | 
					      account: {},
 | 
				
			||||||
      events: [],
 | 
					      events: [],
 | 
				
			||||||
      stats: [],
 | 
					      data: {
 | 
				
			||||||
      project: {}
 | 
					        running: 0,
 | 
				
			||||||
 | 
					        stopped: 0,
 | 
				
			||||||
 | 
					        instances: 0,
 | 
				
			||||||
 | 
					        kubernetes: 0,
 | 
				
			||||||
 | 
					        volumes: 0,
 | 
				
			||||||
 | 
					        snapshots: 0,
 | 
				
			||||||
 | 
					        networks: 0,
 | 
				
			||||||
 | 
					        vpcs: 0,
 | 
				
			||||||
 | 
					        ips: 0,
 | 
				
			||||||
 | 
					        templates: 0
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  computed: {
 | 
				
			||||||
 | 
					    entity: function () {
 | 
				
			||||||
 | 
					      if (this.showProject) {
 | 
				
			||||||
 | 
					        return this.project
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return this.account
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  created () {
 | 
					  created () {
 | 
				
			||||||
@ -158,6 +401,9 @@ export default {
 | 
				
			|||||||
      deep: true,
 | 
					      deep: true,
 | 
				
			||||||
      handler (newData, oldData) {
 | 
					      handler (newData, oldData) {
 | 
				
			||||||
        this.project = newData
 | 
					        this.project = newData
 | 
				
			||||||
 | 
					        if (newData.id) {
 | 
				
			||||||
 | 
					          this.fetchData()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    '$i18n.global.locale' (to, from) {
 | 
					    '$i18n.global.locale' (to, from) {
 | 
				
			||||||
@ -168,61 +414,95 @@ export default {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    fetchData () {
 | 
					    fetchData () {
 | 
				
			||||||
      this.stats = [{}, {}, {}, {}, {}, {}]
 | 
					      if (store.getters.project.id) {
 | 
				
			||||||
      api('listVirtualMachines', { state: 'Running', listall: true }).then(json => {
 | 
					        this.listProject()
 | 
				
			||||||
        var count = 0
 | 
					      } else {
 | 
				
			||||||
        if (json && json.listvirtualmachinesresponse) {
 | 
					        this.listAccount()
 | 
				
			||||||
          count = json.listvirtualmachinesresponse.count
 | 
					      }
 | 
				
			||||||
 | 
					      this.updateData()
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    listAccount () {
 | 
				
			||||||
 | 
					      this.loading = true
 | 
				
			||||||
 | 
					      api('listAccounts', { id: this.$store.getters.userInfo.accountid }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        if (json && json.listaccountsresponse && json.listaccountsresponse.account) {
 | 
				
			||||||
 | 
					          this.account = json.listaccountsresponse.account[0]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var tileColor = this.$config.theme['@dashboard-tile-runningvms-bg'] || '#dfe9cc'
 | 
					 | 
				
			||||||
        this.stats.splice(0, 1, { name: this.$t('label.running.vms'), count: count, icon: 'desktop-outlined', bgcolor: tileColor, path: '/vm', query: { state: 'running', filter: 'running' } })
 | 
					 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      api('listVirtualMachines', { state: 'Stopped', listall: true }).then(json => {
 | 
					    },
 | 
				
			||||||
        var count = 0
 | 
					    listProject () {
 | 
				
			||||||
        if (json && json.listvirtualmachinesresponse) {
 | 
					      this.loading = true
 | 
				
			||||||
          count = json.listvirtualmachinesresponse.count
 | 
					      api('listProjects', { id: store.getters.project.id }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        if (json && json.listprojectsresponse && json.listprojectsresponse.project) {
 | 
				
			||||||
 | 
					          this.project = json.listprojectsresponse.project[0]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var tileColor = this.$config.theme['@dashboard-tile-stoppedvms-bg'] || '#edcbce'
 | 
					 | 
				
			||||||
        this.stats.splice(1, 1, { name: this.$t('label.stopped.vms'), count: count, icon: 'poweroff-outlined', bgcolor: tileColor, path: '/vm', query: { state: 'stopped', filter: 'stopped' } })
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      api('listVirtualMachines', { listall: true }).then(json => {
 | 
					 | 
				
			||||||
        var count = 0
 | 
					 | 
				
			||||||
        if (json && json.listvirtualmachinesresponse) {
 | 
					 | 
				
			||||||
          count = json.listvirtualmachinesresponse.count
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        var tileColor = this.$config.theme['@dashboard-tile-totalvms-bg'] || '#ffffff'
 | 
					 | 
				
			||||||
        this.stats.splice(2, 1, { name: this.$t('label.total.vms'), count: count, icon: 'number-outlined', bgcolor: tileColor, path: '/vm' })
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      api('listVolumes', { listall: true }).then(json => {
 | 
					 | 
				
			||||||
        var count = 0
 | 
					 | 
				
			||||||
        if (json && json.listvolumesresponse) {
 | 
					 | 
				
			||||||
          count = json.listvolumesresponse.count
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        var tileColor = this.$config.theme['@dashboard-tile-totalvolumes-bg'] || '#ffffff'
 | 
					 | 
				
			||||||
        this.stats.splice(3, 1, { name: this.$t('label.total.volume'), count: count, icon: 'database-outlined', bgcolor: tileColor, path: '/volume' })
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      api('listNetworks', { listall: true }).then(json => {
 | 
					 | 
				
			||||||
        var count = 0
 | 
					 | 
				
			||||||
        if (json && json.listnetworksresponse) {
 | 
					 | 
				
			||||||
          count = json.listnetworksresponse.count
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        var tileColor = this.$config.theme['@dashboard-tile-totalnetworks-bg'] || '#ffffff'
 | 
					 | 
				
			||||||
        this.stats.splice(4, 1, { name: this.$t('label.total.network'), count: count, icon: 'apartment-outlined', bgcolor: tileColor, path: '/guestnetwork' })
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      api('listPublicIpAddresses', { listall: true }).then(json => {
 | 
					 | 
				
			||||||
        var count = 0
 | 
					 | 
				
			||||||
        if (json && json.listpublicipaddressesresponse) {
 | 
					 | 
				
			||||||
          count = json.listpublicipaddressesresponse.count
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        var tileColor = this.$config.theme['@dashboard-tile-totalips-bg'] || '#ffffff'
 | 
					 | 
				
			||||||
        this.stats.splice(5, 1, { name: this.$t('label.public.ip.addresses'), count: count, icon: 'environment-outlined', bgcolor: tileColor, path: '/publicip' })
 | 
					 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    updateData () {
 | 
				
			||||||
 | 
					      this.data = {
 | 
				
			||||||
 | 
					        running: 0,
 | 
				
			||||||
 | 
					        stopped: 0,
 | 
				
			||||||
 | 
					        instances: 0,
 | 
				
			||||||
 | 
					        kubernetes: 0,
 | 
				
			||||||
 | 
					        volumes: 0,
 | 
				
			||||||
 | 
					        snapshots: 0,
 | 
				
			||||||
 | 
					        networks: 0,
 | 
				
			||||||
 | 
					        vpcs: 0,
 | 
				
			||||||
 | 
					        ips: 0,
 | 
				
			||||||
 | 
					        templates: 0
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.listInstances()
 | 
				
			||||||
      this.listEvents()
 | 
					      this.listEvents()
 | 
				
			||||||
 | 
					      this.loading = true
 | 
				
			||||||
 | 
					      api('listKubernetesClusters', { listall: true, page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.kubernetes = json?.listkubernetesclustersresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listVolumes', { listall: true, page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.volumes = json?.listvolumesresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listSnapshots', { listall: true, page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.snapshots = json?.listsnapshotsresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listNetworks', { listall: true, page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.networks = json?.listnetworksresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listVPCs', { listall: true, page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.vpcs = json?.listvpcsresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listPublicIpAddresses', { listall: true, page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.ips = json?.listpublicipaddressesresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listTemplates', { templatefilter: 'self', listall: true, page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.templates = json?.listtemplatesresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    listInstances (zone) {
 | 
				
			||||||
 | 
					      this.loading = true
 | 
				
			||||||
 | 
					      api('listVirtualMachines', { listall: true, details: 'min', page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.instances = json?.listvirtualmachinesresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listVirtualMachines', { listall: true, details: 'min', state: 'running', page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.running = json?.listvirtualmachinesresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      api('listVirtualMachines', { listall: true, details: 'min', state: 'stopped', page: 1, pagesize: 1 }).then(json => {
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        this.data.stopped = json?.listvirtualmachinesresponse?.count
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    listEvents () {
 | 
					    listEvents () {
 | 
				
			||||||
      const params = {
 | 
					      const params = {
 | 
				
			||||||
        page: 1,
 | 
					        page: 1,
 | 
				
			||||||
        pagesize: 6,
 | 
					        pagesize: 8,
 | 
				
			||||||
        listall: true
 | 
					        listall: true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      this.loading = true
 | 
					      this.loading = true
 | 
				
			||||||
@ -234,6 +514,37 @@ export default {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    getLabel (usageType) {
 | 
				
			||||||
 | 
					      switch (usageType) {
 | 
				
			||||||
 | 
					        case 'vm':
 | 
				
			||||||
 | 
					          return 'label.instances'
 | 
				
			||||||
 | 
					        case 'cpu':
 | 
				
			||||||
 | 
					          return 'label.cpunumber'
 | 
				
			||||||
 | 
					        case 'memory':
 | 
				
			||||||
 | 
					          return 'label.memory'
 | 
				
			||||||
 | 
					        case 'primarystorage':
 | 
				
			||||||
 | 
					          return 'label.primary.storage'
 | 
				
			||||||
 | 
					        case 'secondarystorage':
 | 
				
			||||||
 | 
					          return 'label.secondary.storage'
 | 
				
			||||||
 | 
					        case 'ip':
 | 
				
			||||||
 | 
					          return 'label.public.ips'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return 'label.' + usageType + 's'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    getValue (usageType, value) {
 | 
				
			||||||
 | 
					      switch (usageType) {
 | 
				
			||||||
 | 
					        case 'memory':
 | 
				
			||||||
 | 
					          return parseFloat(value / 1024.0).toFixed(2) + ' GiB'
 | 
				
			||||||
 | 
					        case 'primarystorage':
 | 
				
			||||||
 | 
					          return parseFloat(value).toFixed(2) + ' GiB'
 | 
				
			||||||
 | 
					        case 'secondarystorage':
 | 
				
			||||||
 | 
					          return parseFloat(value).toFixed(2) + ' GiB'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return value
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    getPercentUsed (total, limit) {
 | 
				
			||||||
 | 
					      return (limit === 'Unlimited') ? 0 : (total / limit) * 100
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    getEventColour (event) {
 | 
					    getEventColour (event) {
 | 
				
			||||||
      if (event.level === 'ERROR') {
 | 
					      if (event.level === 'ERROR') {
 | 
				
			||||||
        return 'red'
 | 
					        return 'red'
 | 
				
			||||||
@ -242,13 +553,6 @@ export default {
 | 
				
			|||||||
        return 'green'
 | 
					        return 'green'
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return 'blue'
 | 
					      return 'blue'
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    onTabChange (key) {
 | 
					 | 
				
			||||||
      this.showAddAccount = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (key !== 'Dashboard') {
 | 
					 | 
				
			||||||
        this.showAddAccount = true
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -276,6 +580,23 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .dashboard-card {
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    min-height: 420px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .dashboard-event {
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    overflow-x:hidden;
 | 
				
			||||||
 | 
					    overflow-y: scroll;
 | 
				
			||||||
 | 
					    max-height: 420px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .center {
 | 
				
			||||||
 | 
					    display: block;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @media (max-width: 1200px) {
 | 
					  @media (max-width: 1200px) {
 | 
				
			||||||
    .ant-col-xl-8 {
 | 
					    .ant-col-xl-8 {
 | 
				
			||||||
      width: 100%;
 | 
					      width: 100%;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user