mirror of https://github.com/apache/cloudstack.git
primate: use a-table with pagination instead of a-list (#151)
This converts many components to use a-table with a-pagination than a-list: * Convert MigrateWizard * Convert Firewalls * Convert Port Forwarding * Convert Load Balancing * Convert Egress Configure * Convert IngressEgress Configure * Convert Dedicate VLAN * Convert VPC Tiers tab Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com> Co-authored-by: Ritchie Vincent <ritchie@ritchievincent.co.uk> Co-authored-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
063c865111
commit
0836e45b94
|
|
@ -40,7 +40,7 @@ export default {
|
|||
component: () => import('@/components/view/DetailsTab.vue')
|
||||
}, {
|
||||
name: 'Egress Rules',
|
||||
component: () => import('@/views/network/EgressConfigure.vue'),
|
||||
component: () => import('@/views/network/EgressRulesTab.vue'),
|
||||
show: (record) => { return record.type === 'Isolated' && 'listEgressFirewallRules' in store.getters.apis }
|
||||
}, {
|
||||
name: 'Public IP Addresses',
|
||||
|
|
|
|||
|
|
@ -917,6 +917,7 @@
|
|||
"snmpPort": "SNMP Port",
|
||||
"sockettimeout": "Socket Timeout",
|
||||
"sourcecidr": "Source CIDR",
|
||||
"destcidr": "Destination CIDR",
|
||||
"sourceNat": "Source NAT",
|
||||
"sourceipaddress": "Source IP Address",
|
||||
"sourceport": "Source Port",
|
||||
|
|
|
|||
|
|
@ -16,60 +16,64 @@
|
|||
// under the License.
|
||||
|
||||
<template>
|
||||
<a-list :dataSource="hosts" itemLayout="vertical" class="list" :loading="loading">
|
||||
<div slot="header" class="list__header">
|
||||
<a-input-search
|
||||
placeholder="Search"
|
||||
v-model="searchQuery"
|
||||
@search="fetchData" />
|
||||
</div>
|
||||
<a-list-item
|
||||
slot="renderItem"
|
||||
slot-scope="host, index"
|
||||
class="host-item"
|
||||
:class="{ 'host-item--selected' : selectedIndex === index }"
|
||||
>
|
||||
<div class="host-item__row">
|
||||
<div class="host-item__value">
|
||||
<span class="host-item__title">{{ $t('name') }}</span>
|
||||
{{ host.name }}
|
||||
</div>
|
||||
<div class="host-item__value host-item__value--small">
|
||||
<span class="host-item__title">Suitability</span>
|
||||
<a-icon
|
||||
class="host-item__suitability-icon"
|
||||
type="check-circle"
|
||||
theme="twoTone"
|
||||
twoToneColor="#52c41a"
|
||||
v-if="host.suitableformigration" />
|
||||
<a-icon
|
||||
class="host-item__suitability-icon"
|
||||
type="close-circle"
|
||||
theme="twoTone"
|
||||
twoToneColor="#f5222d"
|
||||
v-else />
|
||||
</div>
|
||||
<div class="host-item__value host-item__value--full">
|
||||
<span class="host-item__title">{{ $t('cpuused') }}</span>
|
||||
{{ host.cpuused }}
|
||||
</div>
|
||||
<div class="host-item__value">
|
||||
<span class="host-item__title">{{ $t('memused') }}</span>
|
||||
{{ host.memoryused | byteToGigabyte }} GB
|
||||
</div>
|
||||
<div class="form">
|
||||
<a-input-search
|
||||
placeholder="Search"
|
||||
v-model="searchQuery"
|
||||
style="margin-bottom: 10px;"
|
||||
@search="fetchData" />
|
||||
<a-table
|
||||
size="small"
|
||||
style="overflow-y: auto"
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:dataSource="hosts"
|
||||
:pagination="false"
|
||||
:rowKey="record => record.id">
|
||||
<div slot="suitability" slot-scope="record">
|
||||
<a-icon
|
||||
class="host-item__suitability-icon"
|
||||
type="check-circle"
|
||||
theme="twoTone"
|
||||
twoToneColor="#52c41a"
|
||||
v-if="record.suitableformigration" />
|
||||
<a-icon
|
||||
class="host-item__suitability-icon"
|
||||
type="close-circle"
|
||||
theme="twoTone"
|
||||
twoToneColor="#f5222d"
|
||||
v-else />
|
||||
</div>
|
||||
<div slot="memused" slot-scope="record">
|
||||
{{ record.memoryused | byteToGigabyte }} GB
|
||||
</div>
|
||||
<template slot="select" slot-scope="record">
|
||||
<a-radio
|
||||
class="host-item__radio"
|
||||
@click="selectedIndex = index"
|
||||
:checked="selectedIndex === index"
|
||||
:disabled="!host.suitableformigration"></a-radio>
|
||||
</div>
|
||||
</a-list-item>
|
||||
<div slot="footer" class="list__footer">
|
||||
<a-button type="primary" :disabled="selectedIndex === null" @click="submitForm">
|
||||
{{ $t('OK') }}
|
||||
@click="selectedHost = record"
|
||||
:checked="record.id === selectedHost.id"
|
||||
:disabled="!record.suitableformigration"></a-radio>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
class="pagination"
|
||||
size="small"
|
||||
:current="page"
|
||||
:pageSize="pageSize"
|
||||
:total="totalCount"
|
||||
:showTotal="total => `Total ${total} items`"
|
||||
:pageSizeOptions="['10', '20', '40', '80', '100']"
|
||||
@change="handleChangePage"
|
||||
@showSizeChange="handleChangePageSize"
|
||||
showSizeChanger/>
|
||||
|
||||
<div style="margin-top: 20px; display: flex; justify-content:flex-end;">
|
||||
<a-button type="primary" :disabled="!selectedHost.id" @click="submitForm">
|
||||
{{ $t('ok') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-list>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -87,8 +91,33 @@ export default {
|
|||
return {
|
||||
loading: true,
|
||||
hosts: [],
|
||||
selectedIndex: null,
|
||||
searchQuery: ''
|
||||
selectedHost: {},
|
||||
searchQuery: '',
|
||||
totalCount: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('name'),
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: this.$t('Suitability'),
|
||||
scopedSlots: { customRender: 'suitability' }
|
||||
},
|
||||
{
|
||||
title: this.$t('cpuused'),
|
||||
dataIndex: 'cpuused'
|
||||
},
|
||||
{
|
||||
title: this.$t('memused'),
|
||||
scopedSlots: { customRender: 'memused' }
|
||||
},
|
||||
{
|
||||
title: this.$t('select'),
|
||||
scopedSlots: { customRender: 'select' }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
|
@ -100,20 +129,24 @@ export default {
|
|||
api('findHostsForMigration', {
|
||||
virtualmachineid: this.resource.id,
|
||||
keyword: this.searchQuery,
|
||||
page: 1,
|
||||
pagesize: 500
|
||||
page: this.page,
|
||||
pagesize: this.pageSize
|
||||
}).then(response => {
|
||||
this.hosts = response.findhostsformigrationresponse.host
|
||||
this.loading = false
|
||||
this.totalCount = response.findhostsformigrationresponse.count
|
||||
if (this.totalCount > 0) {
|
||||
this.totalCount -= 1
|
||||
}
|
||||
}).catch(error => {
|
||||
this.$message.error('Failed to load hosts: ' + error)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
submitForm () {
|
||||
this.loading = true
|
||||
const host = this.hosts[this.selectedIndex]
|
||||
api(host.requiresStorageMotion ? 'migrateVirtualMachineWithVolume' : 'migrateVirtualMachine', {
|
||||
hostid: host.id,
|
||||
api(this.selectedHost.requiresStorageMotion ? 'migrateVirtualMachineWithVolume' : 'migrateVirtualMachine', {
|
||||
hostid: this.selectedHost.id,
|
||||
virtualmachineid: this.resource.id
|
||||
}).then(response => {
|
||||
this.$store.dispatch('AddAsyncJob', {
|
||||
|
|
@ -141,15 +174,23 @@ export default {
|
|||
this.$parent.$parent.close()
|
||||
}).catch(error => {
|
||||
console.error(error)
|
||||
this.$message.error('Failed to migrate host.')
|
||||
this.$message.error(`Failed to migrate VM to host ${this.selectedHost.name}`)
|
||||
})
|
||||
},
|
||||
handleChangePage (page, pageSize) {
|
||||
this.page = page
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
},
|
||||
handleChangePageSize (currentPage, pageSize) {
|
||||
this.page = currentPage
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
byteToGigabyte: value => {
|
||||
if (!value) return ''
|
||||
value = value / Math.pow(10, 9)
|
||||
return value.toFixed(2)
|
||||
return (value / Math.pow(10, 9)).toFixed(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -157,26 +198,10 @@ export default {
|
|||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.list {
|
||||
max-height: 95vh;
|
||||
width: 95vw;
|
||||
overflow-y: scroll;
|
||||
margin: -24px;
|
||||
|
||||
@media (min-width: 1000px) {
|
||||
max-height: 70vh;
|
||||
width: 60vw;
|
||||
}
|
||||
|
||||
&__header,
|
||||
&__footer {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
.form {
|
||||
width: 85vw;
|
||||
@media (min-width: 800px) {
|
||||
width: 750px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,4 +255,8 @@ export default {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -18,41 +18,37 @@
|
|||
<template>
|
||||
<a-spin :spinning="fetchLoading">
|
||||
<a-button type="dashed" icon="plus" style="width: 100%" @click="handleOpenModal">{{ $t('label.dedicate.vlan.vni.range') }}</a-button>
|
||||
<a-list class="list">
|
||||
<a-list-item v-for="item in items" :key="item.id" class="list__item">
|
||||
<div class="list__item-outer-container">
|
||||
<div class="list__item-container">
|
||||
<div class="list__col">
|
||||
<div class="list__label">{{ $t('vlanrange') }}</div>
|
||||
<div>{{ item.guestvlanrange }}</div>
|
||||
</div>
|
||||
<div class="list__col">
|
||||
<div class="list__label">{{ $t('domain') }}</div>
|
||||
<div>{{ item.domain }}</div>
|
||||
</div>
|
||||
<div class="list__col">
|
||||
<div class="list__label">{{ $t('account') }}</div>
|
||||
<div>{{ item.account }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list__col">
|
||||
<div class="list__label">{{ $t('id') }}</div>
|
||||
<div>{{ item.id }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="actions">
|
||||
<a-popconfirm
|
||||
:title="`${$t('label.delete')}?`"
|
||||
@confirm="handleDelete(item)"
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
placement="top"
|
||||
>
|
||||
<a-button icon="delete" type="danger" shape="round"></a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
<a-table
|
||||
size="small"
|
||||
style="overflow-y: auto; margin-top: 20px;"
|
||||
:loading="fetchLoading"
|
||||
:columns="columns"
|
||||
:dataSource="items"
|
||||
:pagination="false"
|
||||
:rowKey="record => record.id">
|
||||
<template slot="actions" slot-scope="record">
|
||||
<a-popconfirm
|
||||
:title="`${$t('label.delete')}?`"
|
||||
@confirm="handleDelete(record)"
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
placement="top"
|
||||
>
|
||||
<a-button icon="delete" type="danger" shape="round"></a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
class="pagination"
|
||||
size="small"
|
||||
:current="page"
|
||||
:pageSize="pageSize"
|
||||
:total="totalCount"
|
||||
:showTotal="total => `Total ${total} items`"
|
||||
:pageSizeOptions="['10', '20', '40', '80', '100']"
|
||||
@change="handleChangePage"
|
||||
@showSizeChange="handleChangePageSize"
|
||||
showSizeChanger/>
|
||||
|
||||
<a-modal v-model="modal" :title="$t('label.dedicate.vlan.vni.range')" @ok="handleSubmit">
|
||||
<a-spin :spinning="formLoading">
|
||||
|
|
@ -147,7 +143,28 @@ export default {
|
|||
accounts: [],
|
||||
projects: [],
|
||||
modal: false,
|
||||
selectedScope: 'account'
|
||||
selectedScope: 'account',
|
||||
totalCount: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('vlanrange'),
|
||||
dataIndex: 'guestvlanrange'
|
||||
},
|
||||
{
|
||||
title: this.$t('domain'),
|
||||
dataIndex: 'domain'
|
||||
},
|
||||
{
|
||||
title: this.$t('account'),
|
||||
dataIndex: 'account'
|
||||
},
|
||||
{
|
||||
title: this.$t('action'),
|
||||
scopedSlots: { customRender: 'actions' }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
|
|
@ -166,20 +183,23 @@ export default {
|
|||
methods: {
|
||||
fetchData () {
|
||||
this.form.resetFields()
|
||||
this.formLoading = true
|
||||
api('listDedicatedGuestVlanRanges', {
|
||||
physicalnetworkid: this.resource.id
|
||||
physicalnetworkid: this.resource.id,
|
||||
page: this.page,
|
||||
pageSize: this.pageSize
|
||||
}).then(response => {
|
||||
this.items = response.listdedicatedguestvlanrangesresponse.dedicatedguestvlanrange
|
||||
? response.listdedicatedguestvlanrangesresponse.dedicatedguestvlanrange : []
|
||||
this.parentFinishLoading()
|
||||
this.formLoading = false
|
||||
this.items = response.listdedicatedguestvlanrangesresponse.dedicatedguestvlanrange || []
|
||||
this.totalCount = response.listdedicatedguestvlanrangesresponse.count || 0
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: `Error ${error.response.status}`,
|
||||
description: error.response.data.errorresponse.errortext
|
||||
description: error.response.data.errorresponse.errortext,
|
||||
duration: 0
|
||||
})
|
||||
this.parentFinishLoading()
|
||||
}).finally(() => {
|
||||
this.formLoading = false
|
||||
this.parentFinishLoading()
|
||||
})
|
||||
},
|
||||
fetchDomains () {
|
||||
|
|
@ -187,8 +207,7 @@ export default {
|
|||
details: 'min',
|
||||
listAll: true
|
||||
}).then(response => {
|
||||
this.domains = response.listdomainsresponse.domain
|
||||
? response.listdomainsresponse.domain : []
|
||||
this.domains = response.listdomainsresponse.domain || []
|
||||
if (this.domains.length > 0) {
|
||||
this.form.setFieldsValue({
|
||||
domain: this.domains[0].id
|
||||
|
|
@ -340,6 +359,16 @@ export default {
|
|||
this.modal = true
|
||||
this.formLoading = true
|
||||
this.fetchDomains()
|
||||
},
|
||||
handleChangePage (page, pageSize) {
|
||||
this.page = page
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
},
|
||||
handleChangePageSize (currentPage, pageSize) {
|
||||
this.page = currentPage
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -381,4 +410,8 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -20,15 +20,15 @@
|
|||
<div>
|
||||
<div class="form">
|
||||
<div class="form__item">
|
||||
<div class="form__label">Source CIDR</div>
|
||||
<div class="form__label">{{ $t('sourcecidr') }}</div>
|
||||
<a-input v-model="newRule.cidrlist"></a-input>
|
||||
</div>
|
||||
<div class="form__item">
|
||||
<div class="form__label">Destination CIDR</div>
|
||||
<div class="form__label">{{ $t('destcidr') }}</div>
|
||||
<a-input v-model="newRule.destcidrlist"></a-input>
|
||||
</div>
|
||||
<div class="form__item">
|
||||
<div class="form__label">Protocol</div>
|
||||
<div class="form__label">{{ $t('protocol') }}</div>
|
||||
<a-select v-model="newRule.protocol" style="width: 100%;" @change="resetRulePorts">
|
||||
<a-select-option value="tcp">TCP</a-select-option>
|
||||
<a-select-option value="udp">UDP</a-select-option>
|
||||
|
|
@ -37,19 +37,19 @@
|
|||
</a-select>
|
||||
</div>
|
||||
<div v-show="newRule.protocol === 'tcp' || newRule.protocol === 'udp'" class="form__item">
|
||||
<div class="form__label">Start Port</div>
|
||||
<div class="form__label">{{ $t('startport') }}</div>
|
||||
<a-input v-model="newRule.startport"></a-input>
|
||||
</div>
|
||||
<div v-show="newRule.protocol === 'tcp' || newRule.protocol === 'udp'" class="form__item">
|
||||
<div class="form__label">End Port</div>
|
||||
<div class="form__label">{{ $t('endport') }}</div>
|
||||
<a-input v-model="newRule.endport"></a-input>
|
||||
</div>
|
||||
<div v-show="newRule.protocol === 'icmp'" class="form__item">
|
||||
<div class="form__label">ICMP Type</div>
|
||||
<div class="form__label">{{ $t('icmptype') }}</div>
|
||||
<a-input v-model="newRule.icmptype"></a-input>
|
||||
</div>
|
||||
<div v-show="newRule.protocol === 'icmp'" class="form__item">
|
||||
<div class="form__label">ICMP Code</div>
|
||||
<div class="form__label">{{ $t('icmpcode') }}</div>
|
||||
<a-input v-model="newRule.icmpcode"></a-input>
|
||||
</div>
|
||||
<div class="form__item">
|
||||
|
|
@ -60,35 +60,39 @@
|
|||
|
||||
<a-divider/>
|
||||
|
||||
<a-list :loading="loading" style="min-height: 25px;">
|
||||
<a-list-item v-for="rule in egressRules" :key="rule.id" class="rule">
|
||||
<div class="rule-container">
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">Source CIDR</div>
|
||||
<div>{{ rule.cidrlist }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">Destination CIDR</div>
|
||||
<div>{{ rule.destcidrlist }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">Protocol</div>
|
||||
<div>{{ rule.protocol | capitalise }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ rule.protocol === 'icmp' ? 'ICMP Type' : 'Start Port' }}</div>
|
||||
<div>{{ rule.icmptype || rule.startport >= 0 ? rule.icmptype || rule.startport : 'All' }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ rule.protocol === 'icmp' ? 'ICMP Code' : 'End Port' }}</div>
|
||||
<div>{{ rule.icmpcode || rule.endport >= 0 ? rule.icmpcode || rule.endport : 'All' }}</div>
|
||||
</div>
|
||||
<div slot="actions">
|
||||
<a-button shape="round" type="danger" icon="delete" @click="deleteRule(rule)" />
|
||||
</div>
|
||||
</div>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
<a-table
|
||||
size="small"
|
||||
style="overflow-y: auto"
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:dataSource="egressRules"
|
||||
:pagination="false"
|
||||
:rowKey="record => record.id">
|
||||
<template slot="protocol" slot-scope="record">
|
||||
{{ record.protocol | capitalise }}
|
||||
</template>
|
||||
<template slot="startport" slot-scope="record">
|
||||
{{ record.icmptype || record.startport >= 0 ? record.icmptype || record.startport : 'All' }}
|
||||
</template>
|
||||
<template slot="endport" slot-scope="record">
|
||||
{{ record.icmpcode || record.endport >= 0 ? record.icmpcode || record.endport : 'All' }}
|
||||
</template>
|
||||
<template slot="actions" slot-scope="record">
|
||||
<a-button shape="round" type="danger" icon="delete" @click="deleteRule(record)" />
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
class="pagination"
|
||||
size="small"
|
||||
:current="page"
|
||||
:pageSize="pageSize"
|
||||
:total="totalCount"
|
||||
:showTotal="total => `Total ${total} items`"
|
||||
:pageSizeOptions="['10', '20', '40', '80', '100']"
|
||||
@change="handleChangePage"
|
||||
@showSizeChange="handleChangePageSize"
|
||||
showSizeChanger/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -96,6 +100,7 @@
|
|||
import { api } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'EgressRulesTab',
|
||||
props: {
|
||||
resource: {
|
||||
type: Object,
|
||||
|
|
@ -115,7 +120,36 @@ export default {
|
|||
icmpcode: null,
|
||||
startport: null,
|
||||
endport: null
|
||||
}
|
||||
},
|
||||
totalCount: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('sourcecidr'),
|
||||
dataIndex: 'cidrlist'
|
||||
},
|
||||
{
|
||||
title: this.$t('destcidr'),
|
||||
dataIndex: 'destcidrlist'
|
||||
},
|
||||
{
|
||||
title: this.$t('protocol'),
|
||||
scopedSlots: { customRender: 'protocol' }
|
||||
},
|
||||
{
|
||||
title: `ICMP Type / Start Port`,
|
||||
scopedSlots: { customRender: 'startport' }
|
||||
},
|
||||
{
|
||||
title: `ICMP Code / End Port`,
|
||||
scopedSlots: { customRender: 'endport' }
|
||||
},
|
||||
{
|
||||
title: this.$t('action'),
|
||||
scopedSlots: { customRender: 'actions' }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
|
@ -141,9 +175,13 @@ export default {
|
|||
this.loading = true
|
||||
api('listEgressFirewallRules', {
|
||||
listAll: true,
|
||||
networkid: this.resource.id
|
||||
networkid: this.resource.id,
|
||||
page: this.page,
|
||||
pageSize: this.pageSize
|
||||
}).then(response => {
|
||||
this.egressRules = response.listegressfirewallrulesresponse.firewallrule
|
||||
this.egressRules = response.listegressfirewallrulesresponse.firewallrule || []
|
||||
this.totalCount = response.listegressfirewallrulesresponse.count || 0
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
|
@ -211,6 +249,16 @@ export default {
|
|||
this.newRule.icmpcode = null
|
||||
this.newRule.startport = null
|
||||
this.newRule.endport = null
|
||||
},
|
||||
handleChangePage (page, pageSize) {
|
||||
this.page = page
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
},
|
||||
handleChangePageSize (currentPage, pageSize) {
|
||||
this.page = currentPage
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -300,4 +348,7 @@ export default {
|
|||
}
|
||||
|
||||
}
|
||||
.pagination {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -55,36 +55,41 @@
|
|||
|
||||
<a-divider/>
|
||||
|
||||
<a-list :loading="loading" style="min-height: 25px;">
|
||||
<a-list-item v-for="rule in firewallRules" :key="rule.id" class="rule">
|
||||
<div class="rule-container">
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('sourcecidr') }}</div>
|
||||
<div>{{ rule.cidrlist }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('protocol') }}</div>
|
||||
<div>{{ rule.protocol | capitalise }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ rule.protocol === 'icmp' ? $t('icmptype') : $t('startport') }}</div>
|
||||
<div>{{ rule.icmptype || rule.startport >= 0 ? rule.icmptype || rule.startport : $t('all') }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ rule.protocol === 'icmp' ? 'ICMP Code' : 'End Port' }}</div>
|
||||
<div>{{ rule.icmpcode || rule.endport >= 0 ? rule.icmpcode || rule.endport : $t('all') }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('state') }}</div>
|
||||
<div>{{ rule.state }}</div>
|
||||
</div>
|
||||
<div slot="actions">
|
||||
<a-button shape="round" icon="tag" class="rule-action" @click="() => openTagsModal(rule.id)" />
|
||||
<a-button shape="round" type="danger" icon="delete" class="rule-action" @click="deleteRule(rule)" />
|
||||
</div>
|
||||
<a-table
|
||||
size="small"
|
||||
style="overflow-y: auto"
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:dataSource="firewallRules"
|
||||
:pagination="false"
|
||||
:rowKey="record => record.id">
|
||||
<template slot="protocol" slot-scope="record">
|
||||
{{ record.protocol | capitalise }}
|
||||
</template>
|
||||
<template slot="startport" slot-scope="record">
|
||||
{{ record.icmptype || record.startport >= 0 ? record.icmptype || record.startport : $t('all') }}
|
||||
</template>
|
||||
<template slot="endport" slot-scope="record">
|
||||
{{ record.icmpcode || record.endport >= 0 ? record.icmpcode || record.endport : $t('all') }}
|
||||
</template>
|
||||
<template slot="actions" slot-scope="record">
|
||||
<div class="actions">
|
||||
<a-button shape="round" icon="tag" class="rule-action" @click="() => openTagsModal(record.id)" />
|
||||
<a-button shape="round" type="danger" icon="delete" class="rule-action" @click="deleteRule(record)" />
|
||||
</div>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
class="pagination"
|
||||
size="small"
|
||||
:current="page"
|
||||
:pageSize="pageSize"
|
||||
:total="totalCount"
|
||||
:showTotal="total => `Total ${total} items`"
|
||||
:pageSizeOptions="['10', '20', '40', '80', '100']"
|
||||
@change="handleChangePage"
|
||||
@showSizeChange="handleChangePageSize"
|
||||
showSizeChanger/>
|
||||
|
||||
<a-modal title="Edit Tags" v-model="tagsModalVisible" :footer="null" :afterClose="closeModal">
|
||||
<div class="add-tags">
|
||||
|
|
@ -96,7 +101,7 @@
|
|||
<p class="add-tags__label">{{ $t('value') }}</p>
|
||||
<a-input v-model="newTag.value"></a-input>
|
||||
</div>
|
||||
<a-button type="primary" @click="() => handleAddTag()">{{ $t('add') }}</a-button>
|
||||
<a-button type="primary" @click="() => handleAddTag()" :loading="addTagLoading">{{ $t('add') }}</a-button>
|
||||
</div>
|
||||
|
||||
<a-divider></a-divider>
|
||||
|
|
@ -129,6 +134,7 @@ export default {
|
|||
data () {
|
||||
return {
|
||||
loading: true,
|
||||
addTagLoading: false,
|
||||
firewallRules: [],
|
||||
newRule: {
|
||||
protocol: 'tcp',
|
||||
|
|
@ -145,7 +151,36 @@ export default {
|
|||
newTag: {
|
||||
key: null,
|
||||
value: null
|
||||
}
|
||||
},
|
||||
totalCount: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('sourcecidr'),
|
||||
dataIndex: 'cidrlist'
|
||||
},
|
||||
{
|
||||
title: this.$t('protocol'),
|
||||
scopedSlots: { customRender: 'protocol' }
|
||||
},
|
||||
{
|
||||
title: `${this.$t('startport')}/${this.$t('icmptype')}`,
|
||||
scopedSlots: { customRender: 'startport' }
|
||||
},
|
||||
{
|
||||
title: `${this.$t('endport')}/${this.$t('icmpcode')}`,
|
||||
scopedSlots: { customRender: 'endport' }
|
||||
},
|
||||
{
|
||||
title: this.$t('state'),
|
||||
dataIndex: 'state'
|
||||
},
|
||||
{
|
||||
title: this.$t('action'),
|
||||
scopedSlots: { customRender: 'actions' }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
|
@ -171,9 +206,12 @@ export default {
|
|||
this.loading = true
|
||||
api('listFirewallRules', {
|
||||
listAll: true,
|
||||
ipaddressid: this.resource.id
|
||||
ipaddressid: this.resource.id,
|
||||
page: this.page,
|
||||
pageSize: this.pageSize
|
||||
}).then(response => {
|
||||
this.firewallRules = response.listfirewallrulesresponse.firewallrule
|
||||
this.firewallRules = response.listfirewallrulesresponse.firewallrule || []
|
||||
this.totalCount = response.listfirewallrulesresponse.count || 0
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: `Error ${error.response.status}`,
|
||||
|
|
@ -271,6 +309,7 @@ export default {
|
|||
})
|
||||
},
|
||||
handleAddTag () {
|
||||
this.addTagLoading = true
|
||||
api('createTags', {
|
||||
'tags[0].key': this.newTag.key,
|
||||
'tags[0].value': this.newTag.value,
|
||||
|
|
@ -305,6 +344,8 @@ export default {
|
|||
description: error.response.data.createtagsresponse.errortext
|
||||
})
|
||||
this.closeModal()
|
||||
}).finally(() => {
|
||||
this.addTagLoading = false
|
||||
})
|
||||
},
|
||||
handleDeleteTag (tag) {
|
||||
|
|
@ -343,6 +384,16 @@ export default {
|
|||
})
|
||||
this.closeModal()
|
||||
})
|
||||
},
|
||||
handleChangePage (page, pageSize) {
|
||||
this.page = page
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
},
|
||||
handleChangePageSize (currentPage, pageSize) {
|
||||
this.page = currentPage
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -434,7 +485,6 @@ export default {
|
|||
}
|
||||
|
||||
.rule-action {
|
||||
margin-bottom: 20px;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
margin-right: 10px;
|
||||
|
|
@ -472,5 +522,8 @@ export default {
|
|||
display: block;
|
||||
margin-left: auto;
|
||||
}
|
||||
.pagination {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -69,49 +69,33 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<a-list>
|
||||
<a-list-item v-for="(rule, index) in rules" :key="index" class="list">
|
||||
<div class="list__col">
|
||||
<div class="list__title">Protocol</div>
|
||||
<div>{{ rule.protocol | capitalise }}</div>
|
||||
<a-table
|
||||
size="small"
|
||||
style="overflow-y: auto"
|
||||
:columns="columns"
|
||||
:dataSource="rules"
|
||||
:pagination="false"
|
||||
:rowKey="record => record.id">
|
||||
<template slot="protocol" slot-scope="record">
|
||||
{{ record.protocol | capitalise }}
|
||||
</template>
|
||||
<template slot="account" slot-scope="record">
|
||||
<div v-if="record.account && record.securitygroupname">
|
||||
{{ record.account }} - {{ record.securitygroupname }}
|
||||
</div>
|
||||
<div v-if="rule.startport" class="list__col">
|
||||
<div class="list__title">Start Port</div>
|
||||
<div>{{ rule.startport }}</div>
|
||||
</div>
|
||||
<div v-if="rule.endport" class="list__col">
|
||||
<div class="list__title">End Port</div>
|
||||
<div>{{ rule.endport }}</div>
|
||||
</div>
|
||||
<div v-if="rule.icmptype" class="list__col">
|
||||
<div class="list__title">ICMP Type</div>
|
||||
<div>{{ rule.icmptype }}</div>
|
||||
</div>
|
||||
<div v-if="rule.icmpcode" class="list__col">
|
||||
<div class="list__title">ICMP Code</div>
|
||||
<div>{{ rule.icmpcode }}</div>
|
||||
</div>
|
||||
<div v-if="rule.cidr" class="list__col">
|
||||
<div class="list__title">CIDR</div>
|
||||
<div>{{ rule.cidr }}</div>
|
||||
</div>
|
||||
<div class="list__col" v-if="rule.account && rule.securitygroupname">
|
||||
<div class="list__title">Account, Security Group</div>
|
||||
<div>{{ rule.account }} - {{ rule.securitygroupname }}</div>
|
||||
</div>
|
||||
<div slot="actions" class="actions">
|
||||
<a-button shape="round" icon="tag" class="rule-action" @click="() => openTagsModal(rule)" />
|
||||
<a-popconfirm
|
||||
:title="$t('label.delete') + '?'"
|
||||
@confirm="handleDeleteRule(rule)"
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<a-button shape="round" type="danger" icon="delete" class="rule-action" />
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</template>
|
||||
<template slot="actions" slot-scope="record">
|
||||
<a-button shape="round" icon="tag" class="rule-action" @click="() => openTagsModal(record)" />
|
||||
<a-popconfirm
|
||||
:title="$t('label.delete') + '?'"
|
||||
@confirm="handleDeleteRule(record)"
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<a-button shape="round" type="danger" icon="delete" class="rule-action" />
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
<a-modal title="Edit Tags" v-model="tagsModalVisible" :footer="null" :afterClose="closeModal">
|
||||
<a-spin v-if="tagsLoading"></a-spin>
|
||||
|
|
@ -187,7 +171,41 @@ export default {
|
|||
selectedRule: null,
|
||||
tagsLoading: false,
|
||||
addType: 'cidr',
|
||||
tabType: null
|
||||
tabType: null,
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('protocol'),
|
||||
scopedSlots: { customRender: 'protocol' }
|
||||
},
|
||||
{
|
||||
title: this.$t('startport'),
|
||||
dataIndex: 'startport'
|
||||
},
|
||||
{
|
||||
title: this.$t('endport'),
|
||||
dataIndex: 'endport'
|
||||
},
|
||||
{
|
||||
title: 'ICMP Type',
|
||||
dataIndex: 'icmptype'
|
||||
},
|
||||
{
|
||||
title: 'ICMP Code',
|
||||
dataIndex: 'icmpcode'
|
||||
},
|
||||
{
|
||||
title: 'CIDR',
|
||||
dataIndex: 'cidr'
|
||||
},
|
||||
{
|
||||
title: 'Account, Security Group',
|
||||
scopedSlots: { customRender: 'account' }
|
||||
},
|
||||
{
|
||||
title: this.$t('action'),
|
||||
scopedSlots: { customRender: 'actions' }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
|||
|
|
@ -59,90 +59,78 @@
|
|||
|
||||
<a-divider />
|
||||
|
||||
<a-list :loading="loading" style="min-height: 25px;">
|
||||
<a-list-item v-for="rule in lbRules" :key="rule.id" class="rule custom-ant-list">
|
||||
<div class="rule-container">
|
||||
<div class="rule__row">
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('name') }}</div>
|
||||
<div>{{ rule.name }}</div>
|
||||
<a-table
|
||||
size="small"
|
||||
style="overflow-y: auto"
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:dataSource="lbRules"
|
||||
:pagination="false"
|
||||
:rowKey="record => record.id">
|
||||
<template slot="algorithm" slot-scope="record">
|
||||
{{ returnAlgorithmName(record.algorithm) }}
|
||||
</template>
|
||||
<template slot="protocol" slot-scope="record">
|
||||
{{ record.protocol | capitalise }}
|
||||
</template>
|
||||
<template slot="stickiness" slot-scope="record">
|
||||
<a-button @click="() => openStickinessModal(record.id)">
|
||||
{{ returnStickinessLabel(record.id) }}
|
||||
</a-button>
|
||||
</template>
|
||||
<template slot="add" slot-scope="record">
|
||||
<a-button type="primary" icon="plus" @click="() => { selectedRule = record; handleOpenAddVMModal() }">
|
||||
{{ $t('add') }}
|
||||
</a-button>
|
||||
</template>
|
||||
<template slot="expandedRowRender" slot-scope="record">
|
||||
<div class="rule-instance-list">
|
||||
<div v-for="instance in record.ruleInstances" :key="instance.loadbalancerruleinstance.id">
|
||||
<div v-for="ip in instance.lbvmipaddresses" :key="ip" class="rule-instance-list__item">
|
||||
<div>
|
||||
<a-icon type="desktop" />
|
||||
<router-link :to="{ path: '/vm/' + record.virtualmachineid }">
|
||||
{{ instance.loadbalancerruleinstance.displayname }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div>{{ ip }}</div>
|
||||
<div><status :text="instance.loadbalancerruleinstance.state" displayText /></div>
|
||||
<a-button
|
||||
size="small"
|
||||
shape="round"
|
||||
type="danger"
|
||||
icon="delete"
|
||||
@click="() => handleDeleteInstanceFromRule(instance, record, ip)" />
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('publicport') }}</div>
|
||||
<div>{{ rule.publicport }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('privateport') }}</div>
|
||||
<div>{{ rule.privateport }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('algorithm') }}</div>
|
||||
<div>{{ returnAlgorithmName(rule.algorithm) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rule__row">
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('protocol') }}</div>
|
||||
<div>{{ rule.protocol | capitalise }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('state') }}</div>
|
||||
<div>{{ rule.state }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('label.action.configure.stickiness') }}</div>
|
||||
<a-button @click="() => openStickinessModal(rule.id)">
|
||||
{{ returnStickinessLabel(rule.id) }}
|
||||
</a-button>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('label.add.VMs') }}</div>
|
||||
<a-button type="primary" icon="plus" @click="() => { selectedRule = rule; handleOpenAddVMModal() }">
|
||||
{{ $t('add') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rule__row" v-if="rule.ruleInstances">
|
||||
<a-collapse :bordered="false" class="rule-instance-collapse">
|
||||
<template v-slot:expandIcon="props">
|
||||
<a-icon type="caret-right" :rotate="props.isActive ? 90 : 0" />
|
||||
</template>
|
||||
<a-collapse-panel header="View Instances">
|
||||
<div class="rule-instance-list">
|
||||
<div v-for="instance in rule.ruleInstances" :key="instance.loadbalancerruleinstance.id">
|
||||
<div v-for="ip in instance.lbvmipaddresses" :key="ip" class="rule-instance-list__item">
|
||||
<div>
|
||||
<a-icon type="desktop" />
|
||||
<router-link :to="{ path: '/vm/' + rule.virtualmachineid }"> {{ instance.loadbalancerruleinstance.displayname }}</router-link>
|
||||
</div>
|
||||
<div>{{ ip }}</div>
|
||||
<div><status :text="instance.loadbalancerruleinstance.state" displayText /></div>
|
||||
<a-button
|
||||
shape="round"
|
||||
type="danger"
|
||||
icon="delete"
|
||||
@click="() => handleDeleteInstanceFromRule(instance, rule, ip)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<a-button shape="circle" icon="edit" class="rule-action" @click="() => openEditRuleModal(rule)"></a-button>
|
||||
<a-button shape="circle" icon="tag" class="rule-action" @click="() => openTagsModal(rule.id)" />
|
||||
</template>
|
||||
<template slot="actions" slot-scope="record">
|
||||
<div class="actions">
|
||||
<a-button size="small" shape="circle" icon="edit" @click="() => openEditRuleModal(record)"></a-button>
|
||||
<a-button size="small" shape="circle" icon="tag" @click="() => openTagsModal(record.id)" />
|
||||
<a-popconfirm
|
||||
:title="$t('label.delete') + '?'"
|
||||
@confirm="handleDeleteRule(rule)"
|
||||
@confirm="handleDeleteRule(record)"
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<a-button shape="circle" type="danger" icon="delete" class="rule-action" />
|
||||
<a-button size="small" shape="circle" type="danger" icon="delete" />
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
class="pagination"
|
||||
size="small"
|
||||
:current="page"
|
||||
:pageSize="pageSize"
|
||||
:total="totalCount"
|
||||
:showTotal="total => `Total ${total} items`"
|
||||
:pageSizeOptions="['10', '20', '40', '80', '100']"
|
||||
@change="handleChangePage"
|
||||
@showSizeChange="handleChangePageSize"
|
||||
showSizeChanger/>
|
||||
|
||||
<a-modal title="Edit Tags" v-model="tagsModalVisible" :footer="null" :afterClose="closeModal" class="tags-modal">
|
||||
<span v-show="tagsModalLoading" class="modal-loading">
|
||||
|
|
@ -393,7 +381,48 @@ export default {
|
|||
addVmModalLoading: false,
|
||||
addVmModalNicLoading: false,
|
||||
vms: [],
|
||||
nics: []
|
||||
nics: [],
|
||||
totalCount: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('name'),
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: this.$t('publicport'),
|
||||
dataIndex: 'publicport'
|
||||
},
|
||||
{
|
||||
title: this.$t('privateport'),
|
||||
dataIndex: 'privateport'
|
||||
},
|
||||
{
|
||||
title: this.$t('algorithm'),
|
||||
scopedSlots: { customRender: 'algorithm' }
|
||||
},
|
||||
{
|
||||
title: this.$t('protocol'),
|
||||
scopedSlots: { customRender: 'protocol' }
|
||||
},
|
||||
{
|
||||
title: this.$t('state'),
|
||||
dataIndex: 'state'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.action.configure.stickiness'),
|
||||
scopedSlots: { customRender: 'stickiness' }
|
||||
},
|
||||
{
|
||||
title: this.$t('label.add.VMs'),
|
||||
scopedSlots: { customRender: 'add' }
|
||||
},
|
||||
{
|
||||
title: this.$t('action'),
|
||||
scopedSlots: { customRender: 'actions' }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
|
@ -421,11 +450,12 @@ export default {
|
|||
this.stickinessPolicies = []
|
||||
api('listLoadBalancerRules', {
|
||||
listAll: true,
|
||||
publicipid: this.resource.id
|
||||
publicipid: this.resource.id,
|
||||
page: this.page,
|
||||
pageSize: this.pageSize
|
||||
}).then(response => {
|
||||
this.lbRules = response.listloadbalancerrulesresponse.loadbalancerrule
|
||||
? response.listloadbalancerrulesresponse.loadbalancerrule
|
||||
: []
|
||||
this.lbRules = response.listloadbalancerrulesresponse.loadbalancerrule || []
|
||||
this.totalCount = response.listloadbalancerrulesresponse.count || 0
|
||||
}).then(() => {
|
||||
if (this.lbRules.length > 0) {
|
||||
setTimeout(() => {
|
||||
|
|
@ -1041,6 +1071,16 @@ export default {
|
|||
this.newRule.virtualmachineid = []
|
||||
this.newTagsForm.resetFields()
|
||||
this.stickinessPolicyForm.resetFields()
|
||||
},
|
||||
handleChangePage (page, pageSize) {
|
||||
this.page = page
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
},
|
||||
handleChangePageSize (currentPage, pageSize) {
|
||||
this.page = currentPage
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1370,4 +1410,16 @@ export default {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
button {
|
||||
&:not(:last-child) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -71,37 +71,47 @@
|
|||
|
||||
<a-divider/>
|
||||
|
||||
<a-list :loading="loading" style="min-height: 25px;">
|
||||
<a-list-item v-for="rule in portForwardRules" :key="rule.id" class="rule">
|
||||
<div class="rule-container">
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('privateport') }}</div>
|
||||
<div>{{ rule.privateport }} - {{ rule.privateendport }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('publicport') }}</div>
|
||||
<div>{{ rule.publicport }} - {{ rule.publicendport }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('protocol') }}</div>
|
||||
<div>{{ rule.protocol | capitalise }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('state') }}</div>
|
||||
<div>{{ rule.state }}</div>
|
||||
</div>
|
||||
<div class="rule__item">
|
||||
<div class="rule__title">{{ $t('vm') }}</div>
|
||||
<div class="rule__title"></div>
|
||||
<div><a-icon type="desktop"/> <router-link :to="{ path: '/vm/' + rule.virtualmachineid }">{{ rule.virtualmachinename }}</router-link> ({{ rule.vmguestip }})</div>
|
||||
</div>
|
||||
<div slot="actions">
|
||||
<a-button shape="round" icon="tag" class="rule-action" @click="() => openTagsModal(rule.id)" />
|
||||
<a-button shape="round" type="danger" icon="delete" class="rule-action" @click="deleteRule(rule)" />
|
||||
</div>
|
||||
<a-table
|
||||
size="small"
|
||||
style="overflow-y: auto"
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:dataSource="portForwardRules"
|
||||
:pagination="false"
|
||||
:rowKey="record => record.id">
|
||||
<template slot="privateport" slot-scope="record">
|
||||
{{ record.privateport }} - {{ record.privateendport }}
|
||||
</template>
|
||||
<template slot="publicport" slot-scope="record">
|
||||
{{ record.publicport }} - {{ record.publicendport }}
|
||||
</template>
|
||||
<template slot="protocol" slot-scope="record">
|
||||
{{ record.protocol | capitalise }}
|
||||
</template>
|
||||
<template slot="vm" slot-scope="record">
|
||||
<div><a-icon type="desktop"/>
|
||||
<router-link
|
||||
:to="{ path: '/vm/' + record.virtualmachineid }">
|
||||
{{ record.virtualmachinename }}</router-link> ({{ record.vmguestip }})</div>
|
||||
</template>
|
||||
<template slot="actions" slot-scope="record">
|
||||
<div class="actions">
|
||||
<a-button shape="round" icon="tag" class="rule-action" @click="() => openTagsModal(record.id)" />
|
||||
<a-button shape="round" type="danger" icon="delete" class="rule-action" @click="deleteRule(record)" />
|
||||
</div>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
class="pagination"
|
||||
size="small"
|
||||
:current="page"
|
||||
:pageSize="pageSize"
|
||||
:total="totalCount"
|
||||
:showTotal="total => `Total ${total} items`"
|
||||
:pageSizeOptions="['10', '20', '40', '80', '100']"
|
||||
@change="handleChangePage"
|
||||
@showSizeChange="handleChangePageSize"
|
||||
showSizeChanger/>
|
||||
|
||||
<a-modal title="Edit Tags" v-model="tagsModalVisible" :footer="null" :afterClose="closeModal">
|
||||
<span v-show="tagsModalLoading" class="tags-modal-loading">
|
||||
|
|
@ -227,7 +237,36 @@ export default {
|
|||
addVmModalLoading: false,
|
||||
addVmModalNicLoading: false,
|
||||
vms: [],
|
||||
nics: []
|
||||
nics: [],
|
||||
totalCount: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('privateport'),
|
||||
scopedSlots: { customRender: 'privateport' }
|
||||
},
|
||||
{
|
||||
title: this.$t('publicport'),
|
||||
scopedSlots: { customRender: 'publicport' }
|
||||
},
|
||||
{
|
||||
title: this.$t('protocol'),
|
||||
scopedSlots: { customRender: 'protocol' }
|
||||
},
|
||||
{
|
||||
title: this.$t('state'),
|
||||
dataIndex: 'state'
|
||||
},
|
||||
{
|
||||
title: this.$t('vm'),
|
||||
scopedSlots: { customRender: 'vm' }
|
||||
},
|
||||
{
|
||||
title: this.$t('action'),
|
||||
scopedSlots: { customRender: 'actions' }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
|
@ -253,9 +292,12 @@ export default {
|
|||
this.loading = true
|
||||
api('listPortForwardingRules', {
|
||||
listAll: true,
|
||||
ipaddressid: this.resource.id
|
||||
ipaddressid: this.resource.id,
|
||||
page: this.page,
|
||||
pageSize: this.pageSize
|
||||
}).then(response => {
|
||||
this.portForwardRules = response.listportforwardingrulesresponse.portforwardingrule
|
||||
this.portForwardRules = response.listportforwardingrulesresponse.portforwardingrule || []
|
||||
this.totalCount = response.listportforwardingrulesresponse.count || 0
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: `Error ${error.response.status}`,
|
||||
|
|
@ -487,6 +529,16 @@ export default {
|
|||
})
|
||||
this.closeModal()
|
||||
})
|
||||
},
|
||||
handleChangePage (page, pageSize) {
|
||||
this.page = page
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
},
|
||||
handleChangePageSize (currentPage, pageSize) {
|
||||
this.page = currentPage
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -590,7 +642,6 @@ export default {
|
|||
}
|
||||
|
||||
.rule-action {
|
||||
margin-bottom: 20px;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
margin-right: 10px;
|
||||
|
|
@ -672,4 +723,8 @@ export default {
|
|||
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue