diff --git a/ui/src/components/view/InfoCard.vue b/ui/src/components/view/InfoCard.vue index 4e21f89ce95..befda64b93b 100644 --- a/ui/src/components/view/InfoCard.vue +++ b/ui/src/components/view/InfoCard.vue @@ -344,6 +344,13 @@ , +
+
{{ $t('templatename') }}
+
+ + {{ resource.templatename || resource.templateid }} +
+
{{ $t('serviceofferingname') }}
@@ -352,13 +359,6 @@ {{ resource.serviceofferingname || resource.serviceofferingid }}
-
-
{{ $t('templatename') }}
-
- - {{ resource.templatename || resource.templateid }} -
-
{{ $t('diskoffering') }}
diff --git a/ui/src/locales/en.json b/ui/src/locales/en.json index 3134b000802..0faabc37e35 100644 --- a/ui/src/locales/en.json +++ b/ui/src/locales/en.json @@ -481,6 +481,7 @@ "label.add.ldap.list.users": "List LDAP users", "label.add.list.name":"ACL List Name", "label.add.netScaler.device": "Add Netscaler device", +"label.add.network":"Add Network", "label.add.network.offering": "Add network offering", "label.add.new.gateway": "Add new gateway", "label.add.new.tier": "Add new tier", @@ -1308,5 +1309,7 @@ "writeback": "Write-back disk caching", "writethrough": "Write-through", "none": "None", -"maxcpunumber": "Max CPU Cores" +"maxcpunumber": "Max CPU Cores", +"message.template.iso": "Please select a template or ISO to continue", +"label.launch.vm": "Launch Virtual Machine" } diff --git a/ui/src/views/compute/CreateKubernetesCluster.vue b/ui/src/views/compute/CreateKubernetesCluster.vue index 15b9237a4db..e306d72f4a7 100644 --- a/ui/src/views/compute/CreateKubernetesCluster.vue +++ b/ui/src/views/compute/CreateKubernetesCluster.vue @@ -49,7 +49,7 @@ }" :loading="zoneLoading" :placeholder="apiParams.zoneid.description" - @change="val => { this.handleZoneChanged(this.zones[val]) }"> + @change="val => { this.handleZoneChange(this.zones[val]) }"> {{ opt.name || opt.description }} diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index 4459141407a..4943cbb876c 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -72,11 +72,7 @@ > - + + @update-template-iso="updateFieldValue" /> - + @change="value => this.hypervisor = value" />

@@ -318,8 +311,8 @@ import { mixin, mixinDevice } from '@/utils/mixin.js' import store from '@/store' import InfoCard from '@/components/view/InfoCard' -import ComputeOfferingSelection from './wizard/ComputeOfferingSelection' -import ComputeSelection from './wizard/ComputeSelection' +import ComputeOfferingSelection from '@views/compute/wizard/ComputeOfferingSelection' +import ComputeSelection from '@views/compute/wizard/ComputeSelection' import DiskOfferingSelection from '@views/compute/wizard/DiskOfferingSelection' import DiskSizeSelection from '@views/compute/wizard/DiskSizeSelection' import TemplateIsoSelection from '@views/compute/wizard/TemplateIsoSelection' @@ -424,6 +417,7 @@ export default { initDataConfig: {}, defaultNetwork: '', networkConfig: [], + dataNetworkCreated: [], tabList: [ { key: 'templateid', @@ -548,14 +542,6 @@ export default { type: 'Routing' }, field: 'hostid' - }, - groups: { - list: 'listInstanceGroups', - options: { - listall: false - }, - isLoad: true, - field: 'group' } } }, @@ -609,14 +595,6 @@ export default { value: keyboard.id } }) - }, - groupsSelectOptions () { - return this.options.groups.map((group) => { - return { - label: group.name, - value: group.id - } - }) } }, watch: { @@ -854,10 +832,23 @@ export default { handleSubmit (e) { console.log('wizard submit') e.preventDefault() - this.form.validateFields((err, values) => { + this.form.validateFields(async (err, values) => { if (err) { return } + + if (!values.templateid && !values.isoid) { + this.$notification.error({ + message: 'Request Failed', + description: this.$t('message.template.iso') + }) + return + } + + this.loading.deploy = true + + let networkIds = [] + const deployVmData = {} // step 1 : select zone deployVmData.zoneid = values.zoneid @@ -902,15 +893,30 @@ export default { // step 5: select an affinity group deployVmData.affinitygroupids = (values.affinitygroupids || []).join(',') // step 6: select network - if (values.networkids && values.networkids.length > 0) { - for (let i = 0; i < values.networkids.length; i++) { - deployVmData['iptonetworklist[' + i + '].networkid'] = values.networkids[i] - if (this.networkConfig.length > 0) { - const networkConfig = this.networkConfig.filter((item) => item.key === values.networkids[i]) - if (networkConfig && networkConfig.length > 0) { - deployVmData['iptonetworklist[' + i + '].ip'] = networkConfig[0].ipAddress ? networkConfig[0].ipAddress : undefined - deployVmData['iptonetworklist[' + i + '].mac'] = networkConfig[0].macAddress ? networkConfig[0].macAddress : undefined + const arrNetwork = [] + networkIds = values.networkids + if (networkIds.length > 0) { + for (let i = 0; i < networkIds.length; i++) { + if (networkIds[i] === this.defaultNetwork) { + const ipToNetwork = { + networkid: this.defaultNetwork } + arrNetwork.unshift(ipToNetwork) + } else { + const ipToNetwork = { + networkid: networkIds[i] + } + arrNetwork.push(ipToNetwork) + } + } + } + for (let j = 0; j < arrNetwork.length; j++) { + deployVmData['iptonetworklist[' + j + '].networkid'] = arrNetwork[j].networkid + if (this.networkConfig.length > 0) { + const networkConfig = this.networkConfig.filter((item) => item.key === arrNetwork[j].networkid) + if (networkConfig && networkConfig.length > 0) { + deployVmData['iptonetworklist[' + j + '].ip'] = networkConfig[0].ipAddress ? networkConfig[0].ipAddress : undefined + deployVmData['iptonetworklist[' + j + '].mac'] = networkConfig[0].macAddress ? networkConfig[0].macAddress : undefined } } } @@ -918,31 +924,34 @@ export default { deployVmData.keypair = values.keypair deployVmData.name = values.name deployVmData.displayname = values.name - const title = this.$t('Launch Virtual Machine') - const description = deployVmData.name ? deployVmData.name : values.zoneid - this.loading.deploy = true + const title = this.$t('label.launch.vm') + const description = values.name || '' + const password = this.$t('password') api('deployVirtualMachine', deployVmData).then(response => { const jobId = response.deployvirtualmachineresponse.jobid if (jobId) { this.$pollJob({ jobId, successMethod: result => { - let successDescription = '' - if (result.jobresult.virtualmachine.name) { - successDescription = result.jobresult.virtualmachine.name - } else { - successDescription = result.jobresult.virtualmachine.id + const vm = result.jobresult.virtualmachine + const name = vm.displayname || vm.name || vm.id + if (vm.password) { + this.$notification.success({ + message: password + ' for ' + name, + description: vm.password, + duration: 0 + }) } - this.$store.dispatch('AddAsyncJob', { - title: title, - jobid: jobId, - description: successDescription, - status: 'progress' - }) }, - loadingMessage: `${title} in progress for ${description}`, + loadingMessage: `${title} in progress`, catchMessage: 'Error encountered while fetching async job result' }) + this.$store.dispatch('AddAsyncJob', { + title: title, + jobid: jobId, + description: description, + status: 'progress' + }) } this.$router.back() }).catch(error => { @@ -1036,12 +1045,12 @@ export default { }) }) }, - fetchAllTemplates (filterKey) { + fetchAllTemplates (filterKeys) { const promises = [] this.options.templates = [] this.loading.templates = true this.templateFilter.forEach((filter) => { - if (filterKey && filterKey !== filter) { + if (filterKeys && !filterKeys.includes(filter)) { return true } promises.push(this.fetchTemplates(filter)) @@ -1095,7 +1104,7 @@ export default { this.tabKey = 'templateid' _.each(this.params, (param, name) => { if (!('isLoad' in param) || param.isLoad) { - this.fetchOptions(param, name, ['zones', 'groups']) + this.fetchOptions(param, name, ['zones']) } }) this.fetchAllTemplates() diff --git a/ui/src/views/compute/wizard/ComputeOfferingSelection.vue b/ui/src/views/compute/wizard/ComputeOfferingSelection.vue index 4403ee49476..6f2304dfb75 100644 --- a/ui/src/views/compute/wizard/ComputeOfferingSelection.vue +++ b/ui/src/views/compute/wizard/ComputeOfferingSelection.vue @@ -137,8 +137,10 @@ export default { this.selectedRowKeys = [this.preFillContent.computeofferingid] this.$emit('select-compute-item', this.preFillContent.computeofferingid) } else { - this.selectedRowKeys = [] - this.$emit('select-compute-item', null) + if (this.computeItems && this.computeItems.length > 0) { + this.selectedRowKeys = [this.computeItems[0].id] + this.$emit('select-compute-item', this.computeItems[0].id) + } } } } diff --git a/ui/src/views/compute/wizard/NetworkConfiguration.vue b/ui/src/views/compute/wizard/NetworkConfiguration.vue index af205680353..d2c0a4dc869 100644 --- a/ui/src/views/compute/wizard/NetworkConfiguration.vue +++ b/ui/src/views/compute/wizard/NetworkConfiguration.vue @@ -19,7 +19,7 @@ 0) { + this.selectedRowKeys = [this.dataItems[0].id] + this.$emit('select-default-network-item', this.dataItems[0].id) + } }, computed: { rowSelection () { @@ -112,6 +114,7 @@ export default { const keyEx = this.dataItems.filter((item) => this.selectedRowKeys.includes(item.id)) if (!keyEx || keyEx.length === 0) { this.selectedRowKeys = [this.dataItems[0].id] + this.$emit('select-default-network-item', this.dataItems[0].id) } } } @@ -122,7 +125,8 @@ export default { this.$emit('select-default-network-item', value[0]) }, updateNetworkData (name, key, value) { - if (this.networks.length === 0) { + const index = this.networks.findIndex(item => item.key === key) + if (index === -1) { const networkItem = {} networkItem.key = key networkItem[name] = value @@ -137,6 +141,15 @@ export default { } }) this.$emit('update-network-config', this.networks) + }, + removeItem (id) { + this.dataItems = this.dataItems.filter(item => item.id !== id) + if (this.selectedRowKeys.includes(id)) { + if (this.dataItems && this.dataItems.length > 0) { + this.selectedRowKeys = [this.dataItems[0].id] + this.$emit('select-default-network-item', this.dataItems[0].id) + } + } } } } diff --git a/ui/src/views/compute/wizard/NetworkSelection.vue b/ui/src/views/compute/wizard/NetworkSelection.vue index 74678b00109..a80c891d32a 100644 --- a/ui/src/views/compute/wizard/NetworkSelection.vue +++ b/ui/src/views/compute/wizard/NetworkSelection.vue @@ -18,17 +18,13 @@ @@ -62,9 +72,13 @@ import _ from 'lodash' import { api } from '@/api' import store from '@/store' +import CreateNetwork from '@/views/network/CreateNetwork' export default { name: 'NetworkSelection', + components: { + CreateNetwork + }, props: { items: { type: Array, @@ -96,7 +110,8 @@ export default { networkOffering: { loading: false, opts: [] - } + }, + showCreateForm: false } }, computed: { @@ -173,8 +188,13 @@ export default { this.selectedRowKeys = this.preFillContent.networkids this.$emit('select-network-item', this.preFillContent.networkids) } else { - this.selectedRowKeys = [] - this.$emit('select-network-item', null) + if (this.items && this.items.length > 0) { + this.selectedRowKeys = [this.items[0].id] + this.$emit('select-network-item', this.selectedRowKeys) + } else { + this.selectedRowKeys = [] + this.$emit('select-network-item', []) + } } } } diff --git a/ui/src/views/compute/wizard/TemplateIsoSelection.vue b/ui/src/views/compute/wizard/TemplateIsoSelection.vue index 7edef3c0ace..bffc9b5f77b 100644 --- a/ui/src/views/compute/wizard/TemplateIsoSelection.vue +++ b/ui/src/views/compute/wizard/TemplateIsoSelection.vue @@ -37,6 +37,7 @@ { + if (this.filter.length === 0) { + this.filter += 'is:' + item + } else { + this.filter += '; is:' + item + } + }) + this.filterDataSource(this.filter) }) }, onClear () { const field = { filter: undefined } this.form.setFieldsValue(field) - if (this.inputDecorator === 'template') { - this.vmFetchTemplates() - } else { - this.vmFetchIsos() - } + this.filter = '' + this.filterDataSource('') }, changeOsName (value) { this.osType = value @@ -288,8 +291,27 @@ export default { } .filter-group { + /deep/.ant-input-affix-wrapper { + float: right; + width: calc(100% - 32px); + + .ant-input { + border-radius: 4px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + /deep/.ant-input-group-addon { - padding: 0 5px; + float: left; + width: 32px; + height: 32px; + border-radius: 4px; + border-right: 0; + border-left: 1px solid #d9d9d9; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + padding: 0 0 0 1px; } &-button { @@ -301,7 +323,7 @@ export default { &-button { position: relative; display: block; - min-height: 25px; + min-height: 30px; &-clear { position: absolute; diff --git a/ui/src/views/network/CreateIsolatedNetworkForm.vue b/ui/src/views/network/CreateIsolatedNetworkForm.vue index 15ebf19ccfe..a4c40a62f31 100644 --- a/ui/src/views/network/CreateIsolatedNetworkForm.vue +++ b/ui/src/views/network/CreateIsolatedNetworkForm.vue @@ -54,7 +54,7 @@ }" :loading="zoneLoading" :placeholder="this.$t('.zoneid')" - @change="val => { this.handleZoneChanged(this.zones[val]) }"> + @change="val => { this.handleZoneChange(this.zones[val]) }"> {{ opt.name || opt.description }} diff --git a/ui/src/views/network/CreateL2NetworkForm.vue b/ui/src/views/network/CreateL2NetworkForm.vue index 4eff20addb9..0489aa7b49a 100644 --- a/ui/src/views/network/CreateL2NetworkForm.vue +++ b/ui/src/views/network/CreateL2NetworkForm.vue @@ -54,7 +54,7 @@ }" :loading="zoneLoading" :placeholder="this.$t('zoneid')" - @change="val => { this.handleZoneChanged(this.zones[val]) }"> + @change="val => { this.handleZoneChange(this.zones[val]) }"> {{ opt.name || opt.description }} diff --git a/ui/src/views/network/CreateSharedNetworkForm.vue b/ui/src/views/network/CreateSharedNetworkForm.vue index 2303feee79b..f47a0085d03 100644 --- a/ui/src/views/network/CreateSharedNetworkForm.vue +++ b/ui/src/views/network/CreateSharedNetworkForm.vue @@ -54,7 +54,7 @@ }" :loading="zoneLoading" :placeholder="this.$t('zoneid')" - @change="val => { this.handleZoneChanged(this.zones[val]) }"> + @change="val => { this.handleZoneChange(this.zones[val]) }"> {{ opt.name || opt.description }} @@ -70,7 +70,7 @@ }" :loading="zoneLoading" :placeholder="this.$t('physicalnetworkid')" - @change="val => { this.handleZoneChanged(this.formPhysicalNetworks[val]) }"> + @change="val => { this.handleZoneChange(this.formPhysicalNetworks[val]) }"> {{ opt.name || opt.description }}