Skip to content

Commit 6836a94

Browse files
author
Hoang Nguyen
authored
ui: create a new component and display the instance group as autocomplete (#4820)
1 parent d105d6a commit 6836a94

2 files changed

Lines changed: 234 additions & 2 deletions

File tree

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/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>

0 commit comments

Comments
 (0)