blob: 96a6d28ecf1887e9addb3bfab572ff8dca75f135 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
<template>
<div>
<a-input-search
style="width: 25vw; float: right; margin-bottom: 10px; z-index: 8"
:placeholder="$t('label.search')"
v-model:value="filter"
@search="handleSearch" />
<a-button type="primary" @click="onCreateNetworkClick" style="float: right; margin-right: 5px; z-index: 8" v-if="showCreateButton">
{{ $t('label.create.network') }}
</a-button>
<a-table
:loading="loading"
:columns="columns"
:dataSource="networkItems"
:rowKey="record => record.id"
:pagination="false"
:rowSelection="rowSelection"
:scroll="{ y: 225 }"
>
<template #name="{record}">
<resource-icon
v-if="record.icon"
:image="record.icon.base64image"
size="1x"
style="margin-right: 5px"/>
<apartment-outlined v-else style="margin-right: 5px" />
{{ record.name }}
</template>
<template #expandedRowRender="{ record }">
<a-list
:key="record.id"
:dataSource="getDetails(record)"
size="small"
>
<template #renderItem="{ item }">
<a-list-item :key="item.id">
<a-list-item-meta
:description="item.description"
>
<template #title>{{ item.title }}</template>
</a-list-item-meta>
</a-list-item>
</template>
</a-list>
</template>
</a-table>
<div style="display: block; text-align: right;">
<a-pagination
size="small"
:current="options.page"
:pageSize="options.pageSize"
:total="rowCount"
:showTotal="total => `${$t('label.total')} ${total} ${$t('label.items')}`"
:pageSizeOptions="['10', '20', '40', '80', '100', '200']"
@change="onChangePage"
@showSizeChange="onChangePageSize"
showSizeChanger>
<template #buildOptionText="props">
<span>{{ props.value }} / {{ $t('label.page') }}</span>
</template>
</a-pagination>
</div>
<a-modal
:visible="showCreateForm"
:title="$t('label.add.network')"
:closable="true"
:maskClosable="false"
:footer="null"
@cancel="showCreateForm = false"
centered
width="auto">
<create-network
:resource="{ zoneid: zoneId }"
@refresh-data="handleSearch"
@close-action="showCreateForm = false"
/>
</a-modal>
</div>
</template>
<script>
import _ from 'lodash'
import { api } from '@/api'
import { isAdmin } from '@/role'
import store from '@/store'
import CreateNetwork from '@/views/network/CreateNetwork'
import ResourceIcon from '@/components/view/ResourceIcon'
export default {
name: 'NetworkSelection',
components: {
CreateNetwork,
ResourceIcon
},
props: {
items: {
type: Array,
default: () => []
},
rowCount: {
type: Number,
default: () => 0
},
value: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: false
},
zoneId: {
type: String,
default: () => ''
},
autoscale: {
type: Boolean,
default: () => false
},
preFillContent: {
type: Object,
default: () => {}
}
},
data () {
return {
filter: '',
selectedRowKeys: [],
vpcs: [],
filteredInfo: null,
networkOffering: {
loading: false,
opts: []
},
showCreateButton: false,
showCreateForm: false,
oldZoneId: null,
options: {
page: 1,
pageSize: 10,
keyword: null
},
networksBeforeCreate: null
}
},
computed: {
columns () {
let vpcFilter = []
if (this.vpcs) {
vpcFilter = this.vpcs.map((vpc) => {
return {
text: vpc.displaytext,
value: vpc.id
}
})
}
return [
{
dataIndex: 'name',
title: this.$t('label.networks'),
slots: { customRender: 'name' },
width: '40%'
},
{
dataIndex: 'type',
title: this.$t('label.guestiptype'),
width: '15%'
},
{
dataIndex: 'vpcName',
title: this.$t('label.vpc'),
width: '20%',
filters: vpcFilter,
filteredValue: _.get(this.filteredInfo, 'id'),
onFilter: (value, record) => {
return record.vpcid === value
}
},
{
dataIndex: 'supportsvmautoscaling',
title: this.$t('label.supportsvmautoscaling'),
width: '25%'
}
]
},
rowSelection () {
if (this.autoscale) {
return {
type: 'radio',
selectedRowKeys: this.selectedRowKeys,
onChange: this.onSelectRow
}
} else {
return {
type: 'checkbox',
selectedRowKeys: this.selectedRowKeys,
onChange: (rows) => {
this.$emit('select-network-item', rows)
}
}
}
},
networkItems () {
return this.items.map((network) => {
const vpc = _.find(this.vpcs, { id: network.vpcid })
return {
...network,
...{
supportsvmautoscaling: network.supportsvmautoscaling ? 'Yes' : 'No',
vpcName: _.get(vpc, 'displaytext')
}
}
})
}
},
watch: {
value (newValue, oldValue) {
if (newValue && !_.isEqual(newValue, oldValue)) {
this.selectedRowKeys = newValue
}
},
loading () {
api('listZones', { id: this.zoneId }).then(json => {
const zoneResponse = json.listzonesresponse.zone || []
this.showCreateButton = false
if (zoneResponse && zoneResponse.length > 0 && (!zoneResponse[0].securitygroupsenabled || (isAdmin() && zoneResponse[0].networktype === 'Advanced'))) {
this.showCreateButton = true
}
})
if (!this.loading) {
if (this.preFillContent.networkids) {
this.selectedRowKeys = this.preFillContent.networkids
this.$emit('select-network-item', this.preFillContent.networkids)
} else {
if (this.items && this.items.length > 0) {
if (this.oldZoneId === this.zoneId) {
return
}
this.oldZoneId = this.zoneId
this.selectedRowKeys = [this.items[0].id]
this.$emit('select-network-item', this.selectedRowKeys)
} else {
this.selectedRowKeys = []
this.$emit('select-network-item', [])
}
}
}
},
items: {
deep: true,
handler () {
if (this.items && this.items.length > 0 &&
this.networksBeforeCreate) {
var user = this.$store.getters.userInfo
for (var network of this.items) {
if (user.account !== network.account ||
user.domainid !== network.domainid ||
(new Date()).getTime() - Date.parse(network.created) > 30000) {
continue
}
var networkFoundInNewList = false
for (var oldNetwork of this.networksBeforeCreate) {
if (oldNetwork.id === network.id) {
networkFoundInNewList = true
break
}
}
if (!networkFoundInNewList) {
this.selectedRowKeys.push(network.id)
this.$emit('select-network-item', this.selectedRowKeys)
break
}
}
this.networksBeforeCreate = null
}
}
}
},
created () {
this.vpcs = []
const projectId = store?.getters?.project?.id || null
var params = {}
if (projectId) {
params.projectid = projectId
}
api('listVPCs', {
params
}).then((response) => {
this.vpcs = _.get(response, 'listvpcsresponse.vpc')
})
},
inject: ['vmFetchNetworks'],
methods: {
fetchVPCs () {
const projectId = store?.getters?.project?.id || null
if (!projectId) {
return false
}
api('listVPCs', {
projectid: store.getters.project.id
}).then((response) => {
this.vpcs = _.get(response, 'listvpcsresponse.vpc')
})
},
getDetails (network) {
const detail = [
{
title: this.$t('label.description'),
description: network.displaytext
},
{
title: this.$t('label.networkofferingid'),
description: network.networkofferingdisplaytext
}
]
if (network.type !== 'L2') {
detail.push({
title: this.$t('label.cidr'),
description: network.cidr
})
}
return detail
},
handleSearch (value) {
this.filter = value
this.options.page = 1
this.options.pageSize = 10
this.options.keyword = this.filter
this.$emit('handle-search-filter', this.options)
},
onChangePage (page, pageSize) {
this.options.page = page
this.options.pageSize = pageSize
this.$emit('handle-search-filter', this.options)
},
onChangePageSize (page, pageSize) {
this.options.page = page
this.options.pageSize = pageSize
this.$emit('handle-search-filter', this.options)
},
onSelectRow (value) {
this.selectedRowKeys = value
this.$emit('select-network-item', value[0])
},
listNetworkOfferings () {
return new Promise((resolve, reject) => {
const args = {}
args.forvpc = false
args.zoneid = this.zoneId
args.guestiptype = 'Isolated'
args.supportedServices = 'SourceNat'
args.specifyvlan = false
args.state = 'Enabled'
api('listNetworkOfferings', args).then(json => {
const listNetworkOfferings = json.listnetworkofferingsresponse.networkoffering || []
resolve(listNetworkOfferings)
}).catch(error => {
resolve(error)
})
})
},
onCreateNetworkClick () {
this.networksBeforeCreate = this.items
this.showCreateForm = true
}
}
}
</script>
<style lang="less" scoped>
.ant-table-wrapper {
margin: 2rem 0;
}
</style>