Skip to content

Commit 850ea61

Browse files
committed
Merge remote-tracking branch 'origin/4.15'
2 parents 775de36 + faf27e2 commit 850ea61

16 files changed

Lines changed: 323 additions & 30 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class CreateRoleCmd extends RoleCmd {
4242
/////////////////////////////////////////////////////
4343

4444
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true,
45-
description = "creates a role with this unique name", validations = {ApiArgValidator.NotNullOrEmpty})
45+
description = "Creates a role with this unique name", validations = {ApiArgValidator.NotNullOrEmpty})
4646
private String roleName;
4747

4848
@Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class,

ui/public/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@
481481
"label.baremetalmac": "Host MAC",
482482
"label.baremetalmemory": "Memory (in MB)",
483483
"label.based.on": "Based on",
484+
"label.based.on.role.id.or.type": "Creates a role based on either role id or type",
484485
"label.basic": "Basic",
485486
"label.basic.mode": "Basic Mode",
486487
"label.basicsetup": "Basic setup",
@@ -1836,6 +1837,7 @@
18361837
"label.rule.number": "Rule Number",
18371838
"label.rules": "Rules",
18381839
"label.rules.file": "Rules File",
1840+
"label.rules.file.to.import": "Rule defintions CSV file to import",
18391841
"label.rules.file.import.description": "Click or drag rule defintions CSV file to import",
18401842
"label.run.proxy.locally": "Run proxy locally",
18411843
"label.running": "Running VMs",

ui/src/components/view/InfoCard.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,15 @@
395395
</span>
396396
</div>
397397
<div class="resource-detail-item" v-if="resource.templateid">
398-
<div class="resource-detail-item__label">{{ $t('label.templatename') }}</div>
398+
<div class="resource-detail-item__label">{{ resource.isoid ? $t('label.iso') : $t('label.templatename') }}</div>
399399
<div class="resource-detail-item__details">
400400
<a-icon type="picture" />
401-
<router-link :to="{ path: '/template/' + resource.templateid }">{{ resource.templatename || resource.templateid }} </router-link>
401+
<div v-if="resource.isoid">
402+
<router-link :to="{ path: '/iso/' + resource.isoid }">{{ resource.isoname || resource.isoid }} </router-link>
403+
</div>
404+
<div v-else>
405+
<router-link :to="{ path: '/template/' + resource.templateid }">{{ resource.templatename || resource.templateid }} </router-link>
406+
</div>
402407
</div>
403408
</div>
404409
<div class="resource-detail-item" v-if="resource.serviceofferingname && resource.serviceofferingid">

ui/src/components/view/ListView.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@
196196
<span style="margin-right:5px" :key="idx">
197197
<span v-if="$store.getters.userInfo.roletype !== 'User'">
198198
<router-link v-if="'user' in item" :to="{ path: '/accountuser', query: { username: item.user, domainid: record.domainid }}">{{ item.account + '(' + item.user + ')' }}</router-link>
199-
<router-link v-else :to="{ path: '/account', query: { name: item.account, domainid: record.domainid } }">{{ item.account }}</router-link>
199+
<router-link v-else :to="{ path: '/account', query: { name: item.account, domainid: record.domainid, dataView: true } }">{{ item.account }}</router-link>
200200
</span>
201201
<span v-else>{{ item.user ? item.account + '(' + item.user + ')' : item.account }}</span>
202202
</span>
@@ -207,7 +207,7 @@
207207
v-if="'quota' in record && $router.resolve(`${$route.path}/${record.account}`) !== '404'"
208208
:to="{ path: `${$route.path}/${record.account}`, query: { account: record.account, domainid: record.domainid, quota: true } }">{{ text }}</router-link>
209209
<router-link :to="{ path: '/account/' + record.accountid }" v-else-if="record.accountid">{{ text }}</router-link>
210-
<router-link :to="{ path: '/account', query: { name: record.account, domainid: record.domainid } }" v-else-if="$store.getters.userInfo.roletype !== 'User'">{{ text }}</router-link>
210+
<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>
211211
<span v-else>{{ text }}</span>
212212
</template>
213213
</span>

ui/src/config/router.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ function generateRouterMap (section) {
131131
map.meta.actions = section.actions
132132
map.meta.filters = section.filters
133133
map.meta.treeView = section.treeView ? section.treeView : false
134-
map.meta.tabs = section.treeView ? section.tabs : {}
134+
map.meta.tabs = section.tabs
135135

136136
map.children = [{
137137
path: '/' + section.name + '/:id',

ui/src/config/section/compute.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ export default {
8787
label: 'label.action.edit.instance',
8888
docHelp: 'adminguide/virtual_machines.html#changing-the-vm-name-os-or-group',
8989
dataView: true,
90-
args: ['name', 'displayname', 'ostypeid', 'isdynamicallyscalable', 'haenable', 'group'],
91-
show: (record) => { return ['Stopped'].includes(record.state) }
90+
popup: true,
91+
show: (record) => { return ['Stopped'].includes(record.state) },
92+
component: () => import('@/views/compute/EditVM.vue')
9293
},
9394
{
9495
api: 'startVirtualMachine',

ui/src/views/AutogenView.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ export default {
528528
529529
this.projectView = Boolean(store.getters.project && store.getters.project.id)
530530
531-
if (this.$route && this.$route.params && this.$route.params.id) {
531+
if ((this.$route && this.$route.params && this.$route.params.id) || this.$route.query.dataView) {
532532
this.dataView = true
533533
if (!refreshed) {
534534
this.resource = {}

ui/src/views/compute/EditVM.vue

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
<template>
19+
<a-spin :spinning="loading">
20+
<a-form
21+
class="form-layout"
22+
layout="vertical"
23+
:form="form"
24+
@submit="handleSubmit">
25+
<a-form-item>
26+
<span slot="label">
27+
{{ $t('label.name') }}
28+
<a-tooltip :title="apiParams.name.description">
29+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
30+
</a-tooltip>
31+
</span>
32+
<a-input
33+
v-decorator="['name', { initialValue: resource.name || '' }]" />
34+
</a-form-item>
35+
<a-form-item>
36+
<span slot="label">
37+
{{ $t('label.displayname') }}
38+
<a-tooltip :title="apiParams.displayname.description">
39+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
40+
</a-tooltip>
41+
</span>
42+
<a-input
43+
v-decorator="['displayname', { initialValue: resource.displayname || '' }]" />
44+
</a-form-item>
45+
<a-form-item>
46+
<span slot="label">
47+
{{ $t('label.ostypeid') }}
48+
<a-tooltip :title="apiParams.ostypeid.description">
49+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
50+
</a-tooltip>
51+
</span>
52+
<a-select
53+
showSearch
54+
optionFilterProp="children"
55+
:filterOption="(input, option) => {
56+
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
57+
}"
58+
:loading="osTypes.loading"
59+
v-decorator="['ostypeid', { initialValue: resource.ostypeid || '' }]">
60+
<a-select-option v-for="(ostype) in osTypes.opts" :key="ostype.id">
61+
{{ ostype.description }}
62+
</a-select-option>
63+
</a-select>
64+
</a-form-item>
65+
<a-form-item>
66+
<span slot="label">
67+
{{ $t('label.isdynamicallyscalable') }}
68+
<a-tooltip :title="apiParams.isdynamicallyscalable.description">
69+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
70+
</a-tooltip>
71+
</span>
72+
<a-switch
73+
:default-checked="resource.isdynamicallyscalable"
74+
v-decorator="['isdynamicallyscalable']" />
75+
</a-form-item>
76+
<a-form-item>
77+
<span slot="label">
78+
{{ $t('label.haenable') }}
79+
<a-tooltip :title="apiParams.haenable.description">
80+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
81+
</a-tooltip>
82+
</span>
83+
<a-switch
84+
:default-checked="resource.haenable"
85+
v-decorator="['haenable']" />
86+
</a-form-item>
87+
<a-form-item>
88+
<span slot="label">
89+
{{ $t('label.group') }}
90+
<a-tooltip :title="apiParams.group.description">
91+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
92+
</a-tooltip>
93+
</span>
94+
<a-auto-complete
95+
v-decorator="['group', { initialValue: resource.group }]"
96+
:filterOption="(input, option) => {
97+
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
98+
}"
99+
:dataSource="groups.opts" />
100+
</a-form-item>
101+
102+
<div :span="24" class="action-button">
103+
<a-button :loading="loading" @click="onCloseAction">{{ this.$t('label.cancel') }}</a-button>
104+
<a-button :loading="loading" type="primary" @click="handleSubmit">{{ this.$t('label.ok') }}</a-button>
105+
</div>
106+
</a-form>
107+
</a-spin>
108+
</template>
109+
110+
<script>
111+
import { api } from '@/api'
112+
113+
export default {
114+
name: 'EditVM',
115+
props: {
116+
action: {
117+
type: Object,
118+
required: true
119+
},
120+
resource: {
121+
type: Object,
122+
required: true
123+
}
124+
},
125+
data () {
126+
return {
127+
loading: false,
128+
osTypes: {
129+
loading: false,
130+
opts: []
131+
},
132+
groups: {
133+
loading: false,
134+
opts: []
135+
}
136+
}
137+
},
138+
beforeCreate () {
139+
this.form = this.$form.createForm(this)
140+
this.apiParams = {}
141+
const apiConfig = this.$store.getters.apis.updateVirtualMachine || {}
142+
apiConfig.params.forEach(param => {
143+
this.apiParams[param.name] = param
144+
})
145+
},
146+
created () {
147+
this.fetchData()
148+
},
149+
methods: {
150+
fetchData () {
151+
this.fetchOsTypes()
152+
this.fetchInstaceGroups()
153+
},
154+
fetchOsTypes () {
155+
this.osTypes.loading = true
156+
this.osTypes.opts = []
157+
api('listOsTypes', { listAll: true }).then(json => {
158+
this.osTypes.opts = json.listostypesresponse.ostype || []
159+
}).catch(error => {
160+
this.$notifyError(error)
161+
}).finally(() => { this.osTypes.loading = false })
162+
},
163+
fetchInstaceGroups () {
164+
this.groups.loading = true
165+
this.groups.opts = []
166+
api('listInstanceGroups', {
167+
account: this.$store.getters.userInfo.account,
168+
domainid: this.$store.getters.userInfo.domainid,
169+
listall: true
170+
}).then(json => {
171+
const groups = json.listinstancegroupsresponse.instancegroup || []
172+
groups.forEach(x => {
173+
this.groups.opts.push(x.name)
174+
})
175+
}).catch(error => {
176+
this.$notifyError(error)
177+
}).finally(() => { this.groups.loading = false })
178+
},
179+
handleSubmit (e) {
180+
e.preventDefault()
181+
this.form.validateFields((err, values) => {
182+
if (err) return
183+
184+
const params = {}
185+
params.id = this.resource.id
186+
params.name = values.name
187+
params.displayname = values.displayname
188+
params.ostypeid = values.ostypeid
189+
params.isdynamicallyscalable = values.isdynamicallyscalable || false
190+
params.haenable = values.haenable || false
191+
params.group = values.group
192+
193+
this.loading = true
194+
195+
api('updateVirtualMachine', params).then(json => {
196+
this.$message.success({
197+
content: `${this.$t('label.action.edit.instance')} - ${values.name}`,
198+
duration: 2
199+
})
200+
this.$emit('refresh-data')
201+
this.onCloseAction()
202+
}).catch(error => {
203+
this.$notifyError(error)
204+
}).finally(() => { this.loading = false })
205+
})
206+
},
207+
onCloseAction () {
208+
this.$emit('close-action')
209+
}
210+
}
211+
}
212+
</script>
213+
214+
<style scoped lang="less">
215+
.form-layout {
216+
width: 80vw;
217+
218+
@media (min-width: 600px) {
219+
width: 450px;
220+
}
221+
222+
.action-button {
223+
text-align: right;
224+
margin-top: 20px;
225+
226+
button {
227+
margin-right: 5px;
228+
}
229+
}
230+
}
231+
</style>

ui/src/views/iam/CreateRole.vue

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,39 @@
2222
:form="form"
2323
@submit="handleSubmit"
2424
layout="vertical">
25-
<a-form-item :label="$t('label.name')">
25+
<a-form-item>
26+
<span slot="label">
27+
{{ $t('label.name') }}
28+
<a-tooltip :title="createRoleApiParams.name.description">
29+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
30+
</a-tooltip>
31+
</span>
2632
<a-input
2733
v-decorator="['name', {
2834
rules: [{ required: true, message: $t('message.error.required.input') }]
2935
}]"
3036
:placeholder="createRoleApiParams.name.description" />
3137
</a-form-item>
3238

33-
<a-form-item :label="$t('label.description')">
39+
<a-form-item>
40+
<span slot="label">
41+
{{ $t('label.description') }}
42+
<a-tooltip :title="createRoleApiParams.description.description">
43+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
44+
</a-tooltip>
45+
</span>
3446
<a-input
3547
v-decorator="['description']"
3648
:placeholder="createRoleApiParams.description.description" />
3749
</a-form-item>
3850

39-
<a-form-item :label="$t('label.based.on')" v-if="'roleid' in createRoleApiParams">
51+
<a-form-item v-if="'roleid' in createRoleApiParams">
52+
<span slot="label">
53+
{{ $t('label.based.on') }}
54+
<a-tooltip :title="$t('label.based.on.role.id.or.type')">
55+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
56+
</a-tooltip>
57+
</span>
4058
<a-radio-group
4159
v-decorator="['using', {
4260
initialValue: this.createRoleUsing
@@ -52,7 +70,13 @@
5270
</a-radio-group>
5371
</a-form-item>
5472

55-
<a-form-item :label="$t('label.type')" v-if="this.createRoleUsing === 'type'">
73+
<a-form-item v-if="this.createRoleUsing === 'type'">
74+
<span slot="label">
75+
{{ $t('label.type') }}
76+
<a-tooltip :title="createRoleApiParams.type.description">
77+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
78+
</a-tooltip>
79+
</span>
5680
<a-select
5781
v-decorator="['type', {
5882
rules: [{ required: true, message: $t('message.error.select') }]
@@ -64,7 +88,13 @@
6488
</a-select>
6589
</a-form-item>
6690

67-
<a-form-item :label="$t('label.role')" v-if="this.createRoleUsing === 'role'">
91+
<a-form-item v-if="this.createRoleUsing === 'role'">
92+
<span slot="label">
93+
{{ $t('label.role') }}
94+
<a-tooltip :title="createRoleApiParams.roleid.description">
95+
<a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
96+
</a-tooltip>
97+
</span>
6898
<a-select
6999
v-decorator="['roleid', {
70100
rules: [{ required: true, message: $t('message.error.select') }]

0 commit comments

Comments
 (0)