views: refactor to new tabs styled component rendering

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2019-10-14 11:20:25 +05:30
parent c023db99f0
commit 3c36a289a1
11 changed files with 287 additions and 245 deletions

View File

@ -57,8 +57,8 @@ export function generateRouterMap (section) {
resourceType: child.resourceType,
params: child.params ? child.params : {},
details: child.details,
actions: child.actions ? child.actions : [],
viewComponent: child.viewComponent
tabs: child.tabs,
actions: child.actions ? child.actions : []
},
component: component
}
@ -101,10 +101,10 @@ export function generateRouterMap (section) {
resourceType: section.resourceType,
params: section.params ? section.params : {},
details: section.details,
actions: section.actions ? section.actions : [],
viewComponent: section.viewComponent
tabs: section.tabs,
actions: section.actions ? section.actions : []
},
component: section.viewComponent ? section.viewComponent : AutogenView
component: section.component ? section.component : AutogenView
}]
}

View File

@ -9,13 +9,19 @@ export default {
icon: 'desktop',
permission: [ 'listVirtualMachinesMetrics', 'listVirtualMachines' ],
resourceType: 'UserVm',
viewComponent: () => import('@/views/compute/InstanceView.vue'),
columns: [
{ 'name': (record) => { return record.displayname } }, 'state', 'instancename',
{ 'ipaddress': (record) => { return record.nic[0].ipaddress } }, 'account', 'zonename',
'cpunumber', 'cpuused', 'cputotal', 'memoryintfreekbs', 'memorytotal',
'networkread', 'networkwrite', 'diskkbsread', 'diskkbswrite', 'diskiopstotal'
],
tabs: [{
name: 'hardware',
component: () => import('@/views/compute/InstanceHardware.vue')
}, {
name: 'settings',
component: () => import('@/views/setting/ResourceSettingsTab.vue')
}],
hidden: ['instancename', 'account'],
actions: [
{

View File

@ -228,6 +228,7 @@
"haenable": "HA Enabled",
"hahost": "HA Enabled",
"haprovider": "HA Provider",
"hardware": "Hardware",
"hastate": "HA State",
"hideipaddressusage": "Hide IP Address Usage",
"host": "IP Address",
@ -795,6 +796,7 @@
"servicelist": "Services",
"serviceofferingid": "Compute offering",
"serviceofferingname": "Compute offering",
"settings": "Settings",
"shareWith": "Share With",
"shrinkok": "Shrink OK",
"size": "Size",

View File

@ -169,8 +169,7 @@
</div>
<div v-if="dataView">
<component :is="$route.meta.viewComponent" :resource="resource" :loading="loading" v-if="$route.meta.viewComponent"/></component>
<detail-view :resource="resource" :loading="loading" v-else />
<resource-view :resource="resource" :loading="loading" :tabs="$route.meta.tabs" />
</div>
<div class="row-element" v-else>
<list-view
@ -204,8 +203,8 @@ import store from '@/store'
import Breadcrumb from '@/components/widgets/Breadcrumb'
import CardView from '@/components/widgets/CardView'
import ChartCard from '@/components/chart/ChartCard'
import DetailView from '@/views/common/DetailView'
import ListView from '@/components/widgets/ListView'
import ResourceView from '@/views/common/ResourceView'
import Status from '@/components/widgets/Status'
export default {
@ -214,7 +213,7 @@ export default {
Breadcrumb,
CardView,
ChartCard,
DetailView,
ResourceView,
ListView,
Status
},

View File

@ -0,0 +1,31 @@
<template>
<a-list
size="small"
:dataSource="$route.meta.details">
<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>
</template>
<script>
export default {
name: 'DetailsTab',
props: {
resource: {
type: Object,
required: true
},
loading: {
type: Boolean,
default: false
}
}
}
</script>

View File

@ -133,8 +133,8 @@
:percent="Number(parseFloat(100.0 * (resource.memoryallocated) / resource.memorytotal).toFixed(2))" />
</span>
</div>
<div class="resource-detail-item" v-if="resource.totalStorage">
<a-icon type="hdd" />{{ (resource.totalStorage / (1024 * 1024 * 1024.0)).toFixed(2) }} GB Storage
<div class="resource-detail-item" v-if="totalStorage">
<a-icon type="hdd" />{{ (totalStorage / (1024 * 1024 * 1024.0)).toFixed(2) }} GB Storage
<div style="margin-left: 25px" v-if="resource.diskkbsread && resource.diskkbswrite && resource.diskioread && resource.diskiowrite">
<a-tag>Read {{ toSize(resource.diskkbsread) }}</a-tag>
<a-tag>Write {{ toSize(resource.diskkbswrite) }}</a-tag><br/>
@ -397,6 +397,8 @@ export default {
},
watch: {
resource: function (newItem, oldItem) {
console.log('reosurce changed in info-card')
console.log(newItem)
this.resource = newItem
this.resourceType = this.$route.meta.resourceType
this.annotationType = ''
@ -432,6 +434,11 @@ export default {
}
}
},
computed: {
totalStorage: function () {
return this.resource.totalStorage
}
},
methods: {
toSize (kb) {
if (!kb) {

View File

@ -2,44 +2,24 @@
<resource-layout>
<div slot="left">
<slot name="info-card">
<info-card :resource="resource" :loading="loading" />
<info-card :key="resource.totalStorage || resource.name || resource.id" :resource="resource" :loading="loading" @resourceChange="resourceChange" />
</slot>
</div>
<div slot="right">
<a-card
:bordered="true"
style="width:100%">
<a-tabs defaultActiveKey="1" @change="onTabChange" style="width:100%">
<a-skeleton active v-if="loading" />
<a-tabs
v-else
:defaultActiveKey="tabs[0].name"
style="width: 100%"
@change="onTabChange" >
<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-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 " />
<component :is="tab.component" :resource="resource" :loading="loading" @resourceChange="resourceChange" />
</a-tab-pane>
</a-tabs>
</a-card>
@ -49,18 +29,15 @@
<script>
import DetailsTab from '@/views/common/DetailsTab'
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 {
name: 'DetailView',
name: 'ResourceView',
components: {
InfoCard,
ListView,
ResourceLayout,
Status
ResourceLayout
},
props: {
resource: {
@ -70,13 +47,19 @@ export default {
loading: {
type: Boolean,
default: false
},
tabs: {
type: Array,
default: function () {
return [{
name: 'details',
component: DetailsTab
}]
}
}
},
data () {
return {
tabs: [{
name: 'details'
}],
settingsColumns: [
{
title: this.$t('name'),
@ -104,6 +87,9 @@ export default {
methods: {
onTabChange (key) {
this.activeTab = key
},
resourceChange (newResource) {
this.resource = newResource
}
}
}

View File

@ -0,0 +1,166 @@
<template>
<div>
<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 :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>
</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>
</div>
</template>
<script>
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 {
name: 'InstanceHardware',
components: {
InfoCard,
ListView,
ResourceLayout,
Status
},
props: {
resource: {
type: Object,
required: true
},
loading: {
type: Boolean,
default: false
}
},
data () {
return {
vm: {},
volumes: [],
totalStorage: 0,
activeKey: ['1', '2', '3']
}
},
created () {
this.vm = this.resource
this.fetchData()
},
watch: {
resource: function (newItem, oldItem) {
this.vm = newItem
this.fetchData()
}
},
methods: {
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
}
this.resource.volumes = this.volumes
this.resource.totalStorage = this.totalStorage
this.$emit('resourceChange', this.resource)
})
}
}
}
</script>
<style lang="less" scoped>
.page-header-wrapper-grid-content-main {
width: 100%;
height: 100%;
min-height: 100%;
transition: 0.3s;
.vm-detail {
.svg-inline--fa {
margin-left: -1px;
margin-right: 8px;
}
span {
margin-left: 10px;
}
margin-bottom: 8px;
}
}
</style>

View File

@ -1,196 +0,0 @@
<template>
<resource-layout>
<info-card slot="left" :resource="resource" :loading="loading" />
<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 :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>
</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>
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 {
name: 'InstanceView',
components: {
InfoCard,
ListView,
ResourceLayout,
Status
},
props: {
resource: {
type: Object,
required: true
},
loading: {
type: Boolean,
default: false
}
},
data () {
return {
vm: {},
volumes: [],
totalStorage: 0,
activeKey: ['1', '2', '3'],
settingsColumns: [
{
title: this.$t('name'),
dataIndex: 'name',
sorter: true
}, {
title: this.$t('value'),
dataIndex: 'value'
}, {
title: this.$t('action'),
dataIndex: 'actions'
}
],
settings: []
}
},
created () {
this.vm = this.resource
},
watch: {
resource: function (newItem, oldItem) {
this.vm = newItem
this.fetchData()
}
},
methods: {
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
}
this.resource.totalStorage = this.totalStorage
})
}
}
}
</script>
<style lang="less" scoped>
.page-header-wrapper-grid-content-main {
width: 100%;
height: 100%;
min-height: 100%;
transition: 0.3s;
.vm-detail {
.svg-inline--fa {
margin-left: -1px;
margin-right: 8px;
}
span {
margin-left: 10px;
}
margin-bottom: 8px;
}
}
</style>

View File

@ -0,0 +1,41 @@
<template>
<div>
TODO: Implement agnostic resource settings table etc.
<list-view
:columns="columns"
:items="settings " />
</div>
</template>
<script>
import ListView from '@/components/widgets/ListView'
export default {
name: 'ResourceSettingsTab',
components: {
ListView
},
props: {
resource: {
type: Object,
required: true
},
loading: {
type: Boolean,
default: false
}
},
data () {
return {
columns: [],
settings: []
}
},
methods: {
}
}
</script>
<style scoped>
</style>