Merge remote-tracking branch 'origin/4.15'

This commit is contained in:
Rohit Yadav 2021-03-18 13:33:15 +05:30
commit 850ea61dc9
16 changed files with 323 additions and 30 deletions

View File

@ -42,7 +42,7 @@ public class CreateRoleCmd extends RoleCmd {
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true,
description = "creates a role with this unique name", validations = {ApiArgValidator.NotNullOrEmpty})
description = "Creates a role with this unique name", validations = {ApiArgValidator.NotNullOrEmpty})
private String roleName;
@Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class,

View File

@ -481,6 +481,7 @@
"label.baremetalmac": "Host MAC",
"label.baremetalmemory": "Memory (in MB)",
"label.based.on": "Based on",
"label.based.on.role.id.or.type": "Creates a role based on either role id or type",
"label.basic": "Basic",
"label.basic.mode": "Basic Mode",
"label.basicsetup": "Basic setup",
@ -1836,6 +1837,7 @@
"label.rule.number": "Rule Number",
"label.rules": "Rules",
"label.rules.file": "Rules File",
"label.rules.file.to.import": "Rule defintions CSV file to import",
"label.rules.file.import.description": "Click or drag rule defintions CSV file to import",
"label.run.proxy.locally": "Run proxy locally",
"label.running": "Running VMs",

View File

@ -395,10 +395,15 @@
</span>
</div>
<div class="resource-detail-item" v-if="resource.templateid">
<div class="resource-detail-item__label">{{ $t('label.templatename') }}</div>
<div class="resource-detail-item__label">{{ resource.isoid ? $t('label.iso') : $t('label.templatename') }}</div>
<div class="resource-detail-item__details">
<a-icon type="picture" />
<router-link :to="{ path: '/template/' + resource.templateid }">{{ resource.templatename || resource.templateid }} </router-link>
<div v-if="resource.isoid">
<router-link :to="{ path: '/iso/' + resource.isoid }">{{ resource.isoname || resource.isoid }} </router-link>
</div>
<div v-else>
<router-link :to="{ path: '/template/' + resource.templateid }">{{ resource.templatename || resource.templateid }} </router-link>
</div>
</div>
</div>
<div class="resource-detail-item" v-if="resource.serviceofferingname && resource.serviceofferingid">

View File

@ -196,7 +196,7 @@
<span style="margin-right:5px" :key="idx">
<span v-if="$store.getters.userInfo.roletype !== 'User'">
<router-link v-if="'user' in item" :to="{ path: '/accountuser', query: { username: item.user, domainid: record.domainid }}">{{ item.account + '(' + item.user + ')' }}</router-link>
<router-link v-else :to="{ path: '/account', query: { name: item.account, domainid: record.domainid } }">{{ item.account }}</router-link>
<router-link v-else :to="{ path: '/account', query: { name: item.account, domainid: record.domainid, dataView: true } }">{{ item.account }}</router-link>
</span>
<span v-else>{{ item.user ? item.account + '(' + item.user + ')' : item.account }}</span>
</span>
@ -207,7 +207,7 @@
v-if="'quota' in record && $router.resolve(`${$route.path}/${record.account}`) !== '404'"
:to="{ path: `${$route.path}/${record.account}`, query: { account: record.account, domainid: record.domainid, quota: true } }">{{ text }}</router-link>
<router-link :to="{ path: '/account/' + record.accountid }" v-else-if="record.accountid">{{ text }}</router-link>
<router-link :to="{ path: '/account', query: { name: record.account, domainid: record.domainid } }" v-else-if="$store.getters.userInfo.roletype !== 'User'">{{ text }}</router-link>
<router-link :to="{ path: '/account', query: { name: record.account, domainid: record.domainid, dataView: true } }" v-else-if="$store.getters.userInfo.roletype !== 'User'">{{ text }}</router-link>
<span v-else>{{ text }}</span>
</template>
</span>

View File

@ -131,7 +131,7 @@ function generateRouterMap (section) {
map.meta.actions = section.actions
map.meta.filters = section.filters
map.meta.treeView = section.treeView ? section.treeView : false
map.meta.tabs = section.treeView ? section.tabs : {}
map.meta.tabs = section.tabs
map.children = [{
path: '/' + section.name + '/:id',

View File

@ -87,8 +87,9 @@ export default {
label: 'label.action.edit.instance',
docHelp: 'adminguide/virtual_machines.html#changing-the-vm-name-os-or-group',
dataView: true,
args: ['name', 'displayname', 'ostypeid', 'isdynamicallyscalable', 'haenable', 'group'],
show: (record) => { return ['Stopped'].includes(record.state) }
popup: true,
show: (record) => { return ['Stopped'].includes(record.state) },
component: () => import('@/views/compute/EditVM.vue')
},
{
api: 'startVirtualMachine',

View File

@ -528,7 +528,7 @@ export default {
this.projectView = Boolean(store.getters.project && store.getters.project.id)
if (this.$route && this.$route.params && this.$route.params.id) {
if ((this.$route && this.$route.params && this.$route.params.id) || this.$route.query.dataView) {
this.dataView = true
if (!refreshed) {
this.resource = {}

View File

@ -0,0 +1,231 @@
// 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>
<a-spin :spinning="loading">
<a-form
class="form-layout"
layout="vertical"
:form="form"
@submit="handleSubmit">
<a-form-item>
<span slot="label">
{{ $t('label.name') }}
<a-tooltip :title="apiParams.name.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-input
v-decorator="['name', { initialValue: resource.name || '' }]" />
</a-form-item>
<a-form-item>
<span slot="label">
{{ $t('label.displayname') }}
<a-tooltip :title="apiParams.displayname.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-input
v-decorator="['displayname', { initialValue: resource.displayname || '' }]" />
</a-form-item>
<a-form-item>
<span slot="label">
{{ $t('label.ostypeid') }}
<a-tooltip :title="apiParams.ostypeid.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-select
showSearch
optionFilterProp="children"
:filterOption="(input, option) => {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:loading="osTypes.loading"
v-decorator="['ostypeid', { initialValue: resource.ostypeid || '' }]">
<a-select-option v-for="(ostype) in osTypes.opts" :key="ostype.id">
{{ ostype.description }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<span slot="label">
{{ $t('label.isdynamicallyscalable') }}
<a-tooltip :title="apiParams.isdynamicallyscalable.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-switch
:default-checked="resource.isdynamicallyscalable"
v-decorator="['isdynamicallyscalable']" />
</a-form-item>
<a-form-item>
<span slot="label">
{{ $t('label.haenable') }}
<a-tooltip :title="apiParams.haenable.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-switch
:default-checked="resource.haenable"
v-decorator="['haenable']" />
</a-form-item>
<a-form-item>
<span slot="label">
{{ $t('label.group') }}
<a-tooltip :title="apiParams.group.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-auto-complete
v-decorator="['group', { initialValue: resource.group }]"
:filterOption="(input, option) => {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:dataSource="groups.opts" />
</a-form-item>
<div :span="24" class="action-button">
<a-button :loading="loading" @click="onCloseAction">{{ this.$t('label.cancel') }}</a-button>
<a-button :loading="loading" type="primary" @click="handleSubmit">{{ this.$t('label.ok') }}</a-button>
</div>
</a-form>
</a-spin>
</template>
<script>
import { api } from '@/api'
export default {
name: 'EditVM',
props: {
action: {
type: Object,
required: true
},
resource: {
type: Object,
required: true
}
},
data () {
return {
loading: false,
osTypes: {
loading: false,
opts: []
},
groups: {
loading: false,
opts: []
}
}
},
beforeCreate () {
this.form = this.$form.createForm(this)
this.apiParams = {}
const apiConfig = this.$store.getters.apis.updateVirtualMachine || {}
apiConfig.params.forEach(param => {
this.apiParams[param.name] = param
})
},
created () {
this.fetchData()
},
methods: {
fetchData () {
this.fetchOsTypes()
this.fetchInstaceGroups()
},
fetchOsTypes () {
this.osTypes.loading = true
this.osTypes.opts = []
api('listOsTypes', { listAll: true }).then(json => {
this.osTypes.opts = json.listostypesresponse.ostype || []
}).catch(error => {
this.$notifyError(error)
}).finally(() => { this.osTypes.loading = false })
},
fetchInstaceGroups () {
this.groups.loading = true
this.groups.opts = []
api('listInstanceGroups', {
account: this.$store.getters.userInfo.account,
domainid: this.$store.getters.userInfo.domainid,
listall: true
}).then(json => {
const groups = json.listinstancegroupsresponse.instancegroup || []
groups.forEach(x => {
this.groups.opts.push(x.name)
})
}).catch(error => {
this.$notifyError(error)
}).finally(() => { this.groups.loading = false })
},
handleSubmit (e) {
e.preventDefault()
this.form.validateFields((err, values) => {
if (err) return
const params = {}
params.id = this.resource.id
params.name = values.name
params.displayname = values.displayname
params.ostypeid = values.ostypeid
params.isdynamicallyscalable = values.isdynamicallyscalable || false
params.haenable = values.haenable || false
params.group = values.group
this.loading = true
api('updateVirtualMachine', params).then(json => {
this.$message.success({
content: `${this.$t('label.action.edit.instance')} - ${values.name}`,
duration: 2
})
this.$emit('refresh-data')
this.onCloseAction()
}).catch(error => {
this.$notifyError(error)
}).finally(() => { this.loading = false })
})
},
onCloseAction () {
this.$emit('close-action')
}
}
}
</script>
<style scoped lang="less">
.form-layout {
width: 80vw;
@media (min-width: 600px) {
width: 450px;
}
.action-button {
text-align: right;
margin-top: 20px;
button {
margin-right: 5px;
}
}
}
</style>

View File

@ -22,7 +22,13 @@
:form="form"
@submit="handleSubmit"
layout="vertical">
<a-form-item :label="$t('label.name')">
<a-form-item>
<span slot="label">
{{ $t('label.name') }}
<a-tooltip :title="createRoleApiParams.name.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-input
v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.required.input') }]
@ -30,13 +36,25 @@
:placeholder="createRoleApiParams.name.description" />
</a-form-item>
<a-form-item :label="$t('label.description')">
<a-form-item>
<span slot="label">
{{ $t('label.description') }}
<a-tooltip :title="createRoleApiParams.description.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-input
v-decorator="['description']"
:placeholder="createRoleApiParams.description.description" />
</a-form-item>
<a-form-item :label="$t('label.based.on')" v-if="'roleid' in createRoleApiParams">
<a-form-item v-if="'roleid' in createRoleApiParams">
<span slot="label">
{{ $t('label.based.on') }}
<a-tooltip :title="$t('label.based.on.role.id.or.type')">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-radio-group
v-decorator="['using', {
initialValue: this.createRoleUsing
@ -52,7 +70,13 @@
</a-radio-group>
</a-form-item>
<a-form-item :label="$t('label.type')" v-if="this.createRoleUsing === 'type'">
<a-form-item v-if="this.createRoleUsing === 'type'">
<span slot="label">
{{ $t('label.type') }}
<a-tooltip :title="createRoleApiParams.type.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-select
v-decorator="['type', {
rules: [{ required: true, message: $t('message.error.select') }]
@ -64,7 +88,13 @@
</a-select>
</a-form-item>
<a-form-item :label="$t('label.role')" v-if="this.createRoleUsing === 'role'">
<a-form-item v-if="this.createRoleUsing === 'role'">
<span slot="label">
{{ $t('label.role') }}
<a-tooltip :title="createRoleApiParams.roleid.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-select
v-decorator="['roleid', {
rules: [{ required: true, message: $t('message.error.select') }]

View File

@ -22,7 +22,13 @@
:form="form"
@submit="handleSubmit"
layout="vertical">
<a-form-item :label="$t('label.rules.file')">
<a-form-item>
<span slot="label">
{{ $t('label.rules.file') }}
<a-tooltip :title="$t('label.rules.file.to.import')">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-upload-dragger
:multiple="false"
:fileList="fileList"
@ -45,7 +51,13 @@
</p>
</a-upload-dragger>
</a-form-item>
<a-form-item :label="$t('label.name')">
<a-form-item>
<span slot="label">
{{ $t('label.name') }}
<a-tooltip :title="importRoleApiParams.name.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-input
v-decorator="['name', {
rules: [{ required: true, message: $t('message.error.required.input') }]
@ -53,13 +65,25 @@
:placeholder="importRoleApiParams.name.description" />
</a-form-item>
<a-form-item :label="$t('label.description')">
<a-form-item>
<span slot="label">
{{ $t('label.description') }}
<a-tooltip :title="importRoleApiParams.description.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-input
v-decorator="['description']"
:placeholder="importRoleApiParams.description.description" />
</a-form-item>
<a-form-item :label="$t('label.type')">
<a-form-item>
<span slot="label">
{{ $t('label.type') }}
<a-tooltip :title="importRoleApiParams.type.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-select
v-decorator="['type', {
rules: [{ required: true, message: $t('message.error.select') }]
@ -71,7 +95,13 @@
</a-select>
</a-form-item>
<a-form-item :label="$t('label.forced')">
<a-form-item>
<span slot="label">
{{ $t('label.forced') }}
<a-tooltip :title="importRoleApiParams.forced.description">
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
</a-tooltip>
</span>
<a-switch
v-decorator="['forced', {
initialValue: false

View File

@ -237,7 +237,7 @@
<a-select-option
v-for="networkOffering in availableNetworkOfferings"
:key="networkOffering.id">
{{ networkOffering.name }}
{{ networkOffering.displaytext || networkOffering.name || networkOffering.description }}
</a-select-option>
</a-select>
</a-form-item>

View File

@ -125,7 +125,7 @@
:placeholder="this.$t('label.networkofferingid')"
@change="val => { this.handleNetworkOfferingChange(this.networkOfferings[val]) }">
<a-select-option v-for="(opt, optIndex) in this.networkOfferings" :key="optIndex">
{{ opt.name || opt.description }}
{{ opt.displaytext || opt.name || opt.description }}
</a-select-option>
</a-select>
</a-form-item>

View File

@ -125,7 +125,7 @@
:placeholder="this.$t('label.networkofferingid')"
@change="val => { this.handleNetworkOfferingChange(this.networkOfferings[val]) }">
<a-select-option v-for="(opt, optIndex) in this.networkOfferings" :key="optIndex">
{{ opt.name || opt.description }}
{{ opt.displaytext || opt.name || opt.description }}
</a-select-option>
</a-select>
</a-form-item>

View File

@ -74,11 +74,6 @@ export default {
actionZoneLoading: false
}
},
watch: {
resource (newItem, oldItem) {
this.fetchData()
}
},
created () {
const promises = []
promises.push(this.fetchActionZoneData())
@ -113,7 +108,6 @@ export default {
})
},
handleRefresh () {
this.fetchData()
},
refreshParent () {
this.$emit('refresh-data')

View File

@ -284,7 +284,7 @@
:placeholder="this.$t('label.networkofferingid')"
@change="val => { this.handleNetworkOfferingChange(this.networkOfferings[val]) }">
<a-select-option v-for="(opt, optIndex) in this.networkOfferings" :key="optIndex">
{{ opt.name || opt.description }}
{{ opt.displaytext || opt.name || opt.description }}
</a-select-option>
</a-select>
</a-form-item>

View File

@ -170,7 +170,7 @@
<a-select
v-decorator="['networkOffering',{rules: [{ required: true, message: `${$t('label.required')}` }]}]">
<a-select-option v-for="item in networkOfferings" :key="item.id" :value="item.id">
{{ item.name }}
{{ item.displaytext || item.name || item.description }}
</a-select-option>
</a-select>
</a-form-item>