views: refactor into a separate layout with slots

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2019-10-12 16:47:02 +05:30
parent 40355f46b0
commit 3c3f550579
4 changed files with 265 additions and 225 deletions

View File

@ -0,0 +1,29 @@
<template>
<div style="padding-top: 12px" class="page-header-index-wide page-header-wrapper-grid-content-main">
<a-row :gutter="12">
<a-col :md="24" :lg="9" style="margin-bottom: 12px">
<slot name="left">
</slot>
</a-col>
<a-col :md="24" :lg="15">
<slot name="right">
</slot>
</a-col>
</a-row>
</div>
</template>
<script>
export default {
name: 'ResourceLayout'
}
</script>
<style lang="less" scoped>
.page-header-wrapper-grid-content-main {
width: 100%;
height: 100%;
min-height: 100%;
transition: 0.3s;
}
</style>

View File

@ -1,51 +1,57 @@
<template>
<div style="padding-top: 12px" class="page-header-index-wide page-header-wrapper-grid-content-main">
<a-row :gutter="12">
<a-col :md="24" :lg="8" style="margin-bottom: 12px">
<slot name="info-card">
<info-card :resource="resource" :loading="loading" />
</slot>
</a-col>
<a-col :md="24" :lg="16">
<a-card
:bordered="true"
style="width:100%">
<a-tabs defaultActiveKey="1" @change="onTabChange" style="width:100%">
<a-tab-pane
v-for="(tab, index) in tabs"
:tab="$t(tab.name)"
:key="index">
<a-card
style="width:100%"
v-if="tab.name === 'details'"
<resource-layout>
<div slot="left">
<slot name="info-card">
<info-card :resource="resource" :loading="loading" />
</slot>
</div>
<div slot="right">
<a-card
:bordered="true"
style="width:100%">
<a-tabs defaultActiveKey="1" @change="onTabChange" style="width:100%">
<a-tab-pane
v-for="tab in tabs"
:tab="$t(tab.name)"
:key="tab.name">
<div
:bordered="false"
style="width:100%"
v-if="tab.name === 'details'" >
<a-skeleton active v-if="loading" />
<a-list
v-else
size="small"
:dataSource="$route.meta.details"
>
<a-skeleton active v-if="loading" />
<a-card-grid
style="width:50%; min-height: 115px; word-break: break-all; text-align: 'center'"
v-for="key in $route.meta.details"
v-if="!loading && key in resource"
:key="key" >
<strong>{{ $t(key) }}</strong><br/>{{ resource[key] }}
</a-card-grid>
</a-card>
<a-list-item slot="renderItem" slot-scope="item" v-if="item in resource">
<div>
<strong>{{ $t(item) }}</strong>
<br/>
<div>
{{ resource[item] }}
</div>
</div>
</a-list-item>
</a-list>
</div>
<list-view
v-if="tab.name === 'settings'"
:columns="settingsColumns"
:items="settings " />
<list-view
v-if="tab.name === 'settings'"
:columns="settingsColumns"
:items="settings " />
</a-tab-pane>
</a-tabs>
</a-card>
</a-col>
</a-row>
</div>
</a-tab-pane>
</a-tabs>
</a-card>
</div>
</resource-layout>
</template>
<script>
import InfoCard from '@/views/common/InfoCard'
import ListView from '@/components/widgets/ListView'
import ResourceLayout from '@/layouts/ResourceLayout'
import Status from '@/components/widgets/Status'
export default {
@ -53,6 +59,7 @@ export default {
components: {
InfoCard,
ListView,
ResourceLayout,
Status
},
props: {
@ -103,10 +110,4 @@ export default {
</script>
<style lang="less" scoped>
.page-header-wrapper-grid-content-main {
width: 100%;
height: 100%;
min-height: 100%;
transition: 0.3s;
}
</style>

View File

@ -24,25 +24,27 @@
</div>
<div class="resource-detail-item" v-if="resource.state || resource.status">
<status :text="resource.state || resource.status" class="resource-detail-item" />
<span style="margin-left: 5px">{{ resource.state || resource.status }}</span>
<span style="margin-left: 4px">{{ resource.state || resource.status }}</span>
</div>
<div class="resource-detail-item" v-if="resource.id">
<a-icon type="barcode" class="resource-detail-item"/>{{ resource.id }}
<a-tooltip placement="right" >
<template slot="title">
<span>Copy</span>
<span>Copy ID</span>
</template>
<a-button shape="circle" type="dashed" size="small" v-clipboard:copy="resource.id">
<a-icon type="copy"/>
<a-button shape="circle" type="dashed" size="small" v-clipboard:copy="resource.id" style="margin-left: -5px">
<a-icon type="barcode" style="padding-left: 4px; margin-top: 4px"/>
</a-button>
</a-tooltip>
<span style="margin-left: 5px;">{{ resource.id }}</span>
</div>
<div class="resource-detail-item">
<slot name="details">
</slot>
</div>
<div class="resource-detail-item" v-if="resource.ipaddress">
<a-icon type="environment" class="resource-detail-item"/>{{ resource.ipaddress }}
<a-icon type="environment" class="resource-detail-item"/>
<span v-if="resource.nic && resource.nic.length > 0">{{ resource.nic.filter(e => { return e.ipaddress }).map(e => { return e.ipaddress }).join(', ') }}</span>
<span v-else>{{ resource.ipaddress }}</span>
</div>
<div class="resource-detail-item" v-if="resource.virtualmachineid">
<a-icon type="desktop" class="resource-detail-item"/>

View File

@ -1,182 +1,177 @@
<template>
<div style="padding-top: 12px" class="page-header-index-wide page-header-wrapper-grid-content-main">
<a-row :gutter="12">
<a-col :md="24" :lg="8" style="margin-bottom: 12px">
<info-card :resource="resource" resourceType="UserVm" showNotes>
<div slot="avatar">
<font-awesome-icon :icon="['fab', osLogo]" size="4x" style="color: #666;" />
<resource-layout>
<info-card slot="left" :resource="resource" :loading="loading">
<div slot="avatar">
<font-awesome-icon :icon="['fab', osLogo]" size="4x" style="color: #666;" />
</div>
<div slot="name">
<h4>{{ vm.displayname || vm.name }}
<a :href="'/client/console?cmd=access&vm=' + vm.id" target="_blank">
<a-button shape="circle" >
<a-icon type="code" />
</a-button>
</a>
</h4>
<div>
<a-tag>{{ vm.instancename }}</a-tag>
<a-tag>{{ vm.hypervisor }}</a-tag> <br/>
<a-tag :color="vm.haenable ? 'green': 'red'">{{ $t('haenable') }}</a-tag>
<a-tag :color="vm.isdynamicallyscalable ? 'green': 'red'">{{ $t('isdynamicallyscalable') }}</a-tag>
</div>
</div>
<div slot="details">
<div class="vm-detail">
<font-awesome-icon :icon="['fab', osLogo]" size="lg"/>{{ guestOsName }}
</div>
<div class="vm-detail" v-if="vm.keypair">
<a-icon type="key" />
<router-link :to="{ path: '/ssh/?name=' + vm.keypair }">
<span style="margin-left: 10px">{{ vm.keypair }}</span>
</router-link>
</div>
<div class="vm-detail">
<a-icon type="laptop" />
<span class="vm-detail">{{ vm.cputotal }} ({{ vm.cpunumber }} CPU x {{ vm.cpuspeed }} Mhz)</span>
<a-progress
style="padding-left: 25px"
size="small"
:percent="vm && vm.cpuused ? parseFloat(vm.cpuused) : 0.0" />
</div>
<div class="vm-detail">
<a-icon type="appstore" />
<span class="vm-detail">{{ vm.memory }} MB Memory
</span>
<a-progress
style="padding-left: 25px"
size="small"
:percent="vm && vm.memorykbs && vm.memoryintfreekbs && vm.memorykbs > vm.memoryintfreekbs ?
Number(parseFloat(100.0 * (vm.memorykbs - vm.memoryintfreekbs) / vm.memorykbs).toFixed(2)) : 0.0" />
</div>
<div class="vm-detail">
<a-icon type="hdd" />
<span class="vm-detail" style="margin-left: 10px">{{ (totalStorage / (1024 * 1024 * 1024.0)).toFixed(2) }} GB Storage
</span>
<div style="margin-left: 25px">
<a-tag>Read {{ toSize(vm.diskkbsread) }}</a-tag>
<a-tag>Write {{ toSize(vm.diskkbswrite) }}</a-tag><br/>
<a-tag>Read (IO) {{ vm.diskioread }}</a-tag>
<a-tag>Write (IO) {{ vm.diskiowrite }}</a-tag>
</div>
<div slot="name">
<h4>{{ vm.displayname || vm.name }}
<a :href="'/client/console?cmd=access&vm=' + vm.id" target="_blank">
<a-button shape="circle" >
<a-icon type="right-square" />
</a-button>
</a>
</h4>
<div>
<a-tag>{{ vm.instancename }}</a-tag>
<a-tag>{{ vm.hypervisor }}</a-tag> <br/>
<a-tag :color="vm.haenable ? 'green': 'red'">{{ $t('haenable') }}</a-tag>
<a-tag :color="vm.isdynamicallyscalable ? 'green': 'red'">{{ $t('isdynamicallyscalable') }}</a-tag>
</div>
</div>
<div class="vm-detail">
<a-icon type="wifi" />
<span style="margin-left: 10px">
<a-tag><a-icon type="arrow-down" /> RX {{ toSize(vm.networkkbsread) }}</a-tag>
<a-tag><a-icon type="arrow-up" /> TX {{ toSize(vm.networkkbswrite) }}</a-tag>
</span>
<div style="margin-left: 25px" v-for="(eth, index) in vm.nic" :key="eth.id">
<a-icon type="api"/> eth{{ index }} {{ eth.ipaddress }}
(<router-link :to="{ path: '/guestnetwork/' + eth.networkid }">{{ eth.networkname }}</router-link>)
</div>
<div slot="details">
<div class="vm-detail">
<font-awesome-icon :icon="['fab', osLogo]" size="lg"/>{{ guestOsName }}
</div>
<div class="vm-detail" v-if="vm.keypair">
<a-icon type="key" />
<router-link :to="{ path: '/ssh/?name=' + vm.keypair }">
<span style="margin-left: 10px">{{ vm.keypair }}</span>
</router-link>
</div>
<div class="vm-detail">
<font-awesome-icon :icon="['fas', 'microchip']" />
<span class="vm-detail"> {{ vm.cputotal }} ({{ vm.cpunumber }} CPU x {{ vm.cpuspeed }} Mhz)
</span>
<a-progress
style="padding-left: 25px"
size="small"
:percent="vm && vm.cpuused ? parseFloat(vm.cpuused) : 0.0" />
</div>
<div class="vm-detail">
<font-awesome-icon :icon="['fas', 'memory']" style="margin-left: -2px"/>
<span class="vm-detail">{{ vm.memory }} MB Memory
</span>
<a-progress
style="padding-left: 25px"
size="small"
:percent="vm && vm.memorykbs && vm.memoryintfreekbs && vm.memorykbs > vm.memoryintfreekbs ?
Number(parseFloat(100.0 * (vm.memorykbs - vm.memoryintfreekbs) / vm.memorykbs).toFixed(2)) : 0.0" />
</div>
<div class="vm-detail">
<font-awesome-icon :icon="['fas', 'database']" />
<span class="vm-detail" style="margin-left: 5px">{{ (totalStorage / (1024 * 1024 * 1024.0)).toFixed(2) }} GB Storage
</span>
<div style="margin-left: 25px">
<a-tag><a-icon type="download" /> Read {{ toSize(vm.diskkbsread) }}</a-tag>
<a-tag><a-icon type="upload" /> Write {{ toSize(vm.diskkbswrite) }}</a-tag><br/>
<a-tag><a-icon type="download" /> Read (IO) {{ vm.diskioread }}</a-tag>
<a-tag><a-icon type="upload" /> Write (IO) {{ vm.diskiowrite }}</a-tag>
</div>
</div>
<div class="vm-detail">
<font-awesome-icon :icon="['fas', 'ethernet']" />
<span class="vm-detail"> {{ vm && vm.nic ? vm.nic.length : 0 }} NIC(s)
<a-tag><a-icon type="arrow-down" /> RX {{ toSize(vm.networkkbsread) }}</a-tag>
<a-tag><a-icon type="arrow-up" /> TX {{ toSize(vm.networkkbswrite) }}</a-tag>
</span>
<div style="margin-left: 25px" v-for="(eth, index) in vm.nic" :key="eth.id">
<a-icon type="api"/> eth{{ index }} {{ eth.ipaddress }}
(<router-link :to="{ path: '/guestnetwork/' + eth.networkid }">{{ eth.networkname }}</router-link>)
</div>
</div>
<div class="vm-detail" v-if="vm.group">
<a-icon type="gold" />
<span style="margin-left: 8px">{{ vm.group }}</span>
</div>
</div>
</info-card>
</a-col>
<a-col :md="24" :lg="16">
<a-card
style="width:100%"
title="Hardware"
:bordered="true"
>
<a-collapse v-model="activeKey">
<a-collapse-panel :header="'ISO: ' + vm.isoname" v-if="vm.isoid" key="1">
<a-list
itemLayout="horizontal">
<a-list-item>
<a-list-item-meta :description="vm.isoid">
<a slot="title" href="">
<router-link :to="{ path: '/iso/' + vm.isoid }">{{ vm.isoname }}</router-link>
</a> ({{ vm.isoname }})
<a-avatar slot="avatar">
<font-awesome-icon :icon="['fas', 'compact-disc']" />
</a-avatar>
</a-list-item-meta>
</a-list-item>
</a-list>
</a-collapse-panel>
</div>
<div class="vm-detail" v-if="vm.group">
<a-icon type="gold" />
<span style="margin-left: 8px">{{ vm.group }}</span>
</div>
</div>
</info-card>
<a-collapse-panel :header="'Disks: ' + volumes.length" key="2">
<a-list
size="small"
itemLayout="horizontal"
:dataSource="volumes"
>
<a-list-item slot="renderItem" slot-scope="item">
<a-list-item-meta>
<div slot="title">
<router-link :to="{ path: '/volume/' + item.id }">{{ item.name }}</router-link> ({{ item.type }}) <br/>
<status :text="item.state" displayText /><br/>
</div>
<div slot="description">
<a-icon type="barcode"/> {{ item.id }}
</div>
<a-avatar slot="avatar">
<font-awesome-icon :icon="['fas', 'database']" />
</a-avatar>
</a-list-item-meta>
<p>
Size: {{ (item.size / (1024 * 1024 * 1024.0)).toFixed(4) }} GB<br/>
Physical Size: {{ (item.physicalsize / (1024 * 1024 * 1024.0)).toFixed(4) }} GB<br/>
Provisioning: {{ item.provisioningtype }}<br/>
Storage Pool: {{ item.storage }} ({{ item.storagetype }})<br/>
</p>
</a-list-item>
</a-list>
<div slot="right">
<a-card
style="width:100%"
title="Hardware"
:bordered="true"
>
<a-collapse v-model="activeKey">
<a-collapse-panel :header="'ISO: ' + vm.isoname" v-if="vm.isoid" key="1">
<a-list
itemLayout="horizontal">
<a-list-item>
<a-list-item-meta :description="vm.isoid">
<a slot="title" href="">
<router-link :to="{ path: '/iso/' + vm.isoid }">{{ vm.isoname }}</router-link>
</a> ({{ vm.isoname }})
<a-avatar slot="avatar">
<a-icon type="usb" />
</a-avatar>
</a-list-item-meta>
</a-list-item>
</a-list>
</a-collapse-panel>
</a-collapse-panel>
<a-collapse-panel :header="'Network Adapter(s): ' + (vm && vm.nic ? vm.nic.length : 0)" key="3" >
<a-list
size="small"
itemLayout="horizontal"
:dataSource="vm.nic"
>
<a-list-item slot="renderItem" slot-scope="item">
<a-list-item-meta>
<div slot="title">
<span v-show="item.isdefault">(Default) </span>
<router-link :to="{ path: '/guestnetwork/' + item.networkid }">{{ item.networkname }} </router-link><br/>
Mac Address: {{ item.macaddress }}<br/>
<span v-if="item.ipaddress">Address: {{ item.ipaddress }} <br/></span>
Netmask: {{ item.netmask }}<br/>
Gateway: {{ item.gateway }}<br/>
</div>
<div slot="description">
<a-icon type="barcode"/> {{ item.id }}
</div>
<a-avatar slot="avatar">
<font-awesome-icon :icon="['fas', 'ethernet']" />
</a-avatar>
</a-list-item-meta>
<p>
Type: {{ item.type }}<br/>
Broadcast URI: {{ item.broadcasturi }}<br/>
Isolation URI: {{ item.isolationuri }}<br/>
</p>
</a-list-item>
</a-list>
</a-collapse-panel>
</a-collapse>
</a-card>
<a-card
style="width:100%; margin-top: 12px"
title="Settings"
:bordered="true"
>
<list-view
:columns="settingsColumns"
:items="settings " />
</a-card>
</a-col>
</a-row>
<a-collapse-panel :header="'Disks: ' + volumes.length" key="2">
<a-list
size="small"
itemLayout="horizontal"
:dataSource="volumes"
>
<a-list-item slot="renderItem" slot-scope="item">
<a-list-item-meta>
<div slot="title">
<router-link :to="{ path: '/volume/' + item.id }">{{ item.name }}</router-link> ({{ item.type }}) <br/>
<status :text="item.state" displayText /><br/>
</div>
<div slot="description">
<a-icon type="barcode"/> {{ item.id }}
</div>
<a-avatar slot="avatar">
<a-icon type="hdd" />
</a-avatar>
</a-list-item-meta>
<p>
Size: {{ (item.size / (1024 * 1024 * 1024.0)).toFixed(4) }} GB<br/>
Physical Size: {{ (item.physicalsize / (1024 * 1024 * 1024.0)).toFixed(4) }} GB<br/>
Provisioning: {{ item.provisioningtype }}<br/>
Storage Pool: {{ item.storage }} ({{ item.storagetype }})<br/>
</p>
</a-list-item>
</a-list>
</div>
</a-collapse-panel>
<a-collapse-panel :header="'Network Adapter(s): ' + (vm && vm.nic ? vm.nic.length : 0)" key="3" >
<a-list
size="small"
itemLayout="horizontal"
:dataSource="vm.nic"
>
<a-list-item slot="renderItem" slot-scope="item">
<a-list-item-meta>
<div slot="title">
<span v-show="item.isdefault">(Default) </span>
<router-link :to="{ path: '/guestnetwork/' + item.networkid }">{{ item.networkname }} </router-link><br/>
Mac Address: {{ item.macaddress }}<br/>
<span v-if="item.ipaddress">Address: {{ item.ipaddress }} <br/></span>
Netmask: {{ item.netmask }}<br/>
Gateway: {{ item.gateway }}<br/>
</div>
<div slot="description">
<a-icon type="barcode"/> {{ item.id }}
</div>
<a-avatar slot="avatar">
<a-icon type="wifi" />
</a-avatar>
</a-list-item-meta>
<p>
Type: {{ item.type }}<br/>
Broadcast URI: {{ item.broadcasturi }}<br/>
Isolation URI: {{ item.isolationuri }}<br/>
</p>
</a-list-item>
</a-list>
</a-collapse-panel>
</a-collapse>
</a-card>
<a-card
style="width:100%; margin-top: 12px"
title="Settings"
:bordered="true"
>
<list-view
:columns="settingsColumns"
:items="settings " />
</a-card>
</div>
</resource-layout>
</template>
<script>
@ -184,6 +179,7 @@
import { api } from '@/api'
import InfoCard from '@/views/common/InfoCard'
import ListView from '@/components/widgets/ListView'
import ResourceLayout from '@/layouts/ResourceLayout'
import Status from '@/components/widgets/Status'
export default {
@ -191,12 +187,17 @@ export default {
components: {
InfoCard,
ListView,
ResourceLayout,
Status
},
props: {
resource: {
type: Object,
required: true
},
loading: {
type: Boolean,
default: false
}
},
data () {
@ -246,8 +247,12 @@ export default {
return parseFloat(kb / (1024.0 * 1024.0)).toFixed(2) + ' GB'
},
fetchData () {
this.volumes = []
api('listVolumes', { 'listall': true, 'virtualmachineid': this.vm.id }).then(json => {
this.volumes = json.listvolumesresponse.volume
if (this.volumes) {
this.volumes.sort((a, b) => { return a.deviceid - b.deviceid })
}
this.totalStorage = 0
for (var volume of this.volumes) {
this.totalStorage += volume.size
@ -293,9 +298,12 @@ export default {
transition: 0.3s;
.vm-detail {
.svg-inline--fa {
margin-left: -2px;
margin-left: -1px;
margin-right: 8px;
}
span {
margin-left: 10px;
}
margin-bottom: 8px;
}
}