You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2020/01/09 07:02:44 UTC
[cloudstack-primate] branch master updated: config: update offering
access action (domain/zone) (#94)
This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack-primate.git
The following commit(s) were added to refs/heads/master by this push:
new de6dede config: update offering access action (domain/zone) (#94)
de6dede is described below
commit de6dedee4ebd445221148d16bc9361d06e5782f4
Author: Abhishek Kumar <ab...@gmail.com>
AuthorDate: Thu Jan 9 12:32:35 2020 +0530
config: update offering access action (domain/zone) (#94)
Update Offering Access action with the action form for:
Compute Offering
Storage Offering
Network Offering
VPC Offering
Fixes #91
Signed-off-by: Abhishek Kumar <ab...@gmail.com>
Co-authored-by: Rohit Yadav <ro...@apache.org>
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
---
src/config/section/offering.js | 28 +++
src/views/offering/UpdateOfferingAccess.vue | 294 ++++++++++++++++++++++++++++
2 files changed, 322 insertions(+)
diff --git a/src/config/section/offering.js b/src/config/section/offering.js
index d3a4c25..14d29de 100644
--- a/src/config/section/offering.js
+++ b/src/config/section/offering.js
@@ -48,6 +48,13 @@ export default {
dataView: true,
args: ['name', 'displaytext']
}, {
+ api: 'updateServiceOffering',
+ icon: 'lock',
+ label: 'Update Offering Access',
+ dataView: true,
+ popup: true,
+ component: () => import('@/views/offering/UpdateOfferingAccess.vue')
+ }, {
api: 'deleteServiceOffering',
icon: 'delete',
label: 'Delete Offering',
@@ -112,6 +119,13 @@ export default {
dataView: true,
args: ['name', 'displaytext']
}, {
+ api: 'updateDiskOffering',
+ icon: 'lock',
+ label: 'Update Offering Access',
+ dataView: true,
+ popup: true,
+ component: () => import('@/views/offering/UpdateOfferingAccess.vue')
+ }, {
api: 'deleteDiskOffering',
icon: 'delete',
label: 'Delete Offering',
@@ -164,6 +178,13 @@ export default {
}
}
}, {
+ api: 'updateNetworkOffering',
+ icon: 'lock',
+ label: 'Update Offering Access',
+ dataView: true,
+ popup: true,
+ component: () => import('@/views/offering/UpdateOfferingAccess.vue')
+ }, {
api: 'deleteNetworkOffering',
icon: 'delete',
label: 'Delete Offering',
@@ -222,6 +243,13 @@ export default {
}
}
}, {
+ api: 'updateVPCOffering',
+ icon: 'lock',
+ label: 'Update Offering Access',
+ dataView: true,
+ popup: true,
+ component: () => import('@/views/offering/UpdateOfferingAccess.vue')
+ }, {
api: 'deleteVPCOffering',
icon: 'delete',
label: 'Delete Offering',
diff --git a/src/views/offering/UpdateOfferingAccess.vue b/src/views/offering/UpdateOfferingAccess.vue
new file mode 100644
index 0000000..4f34602
--- /dev/null
+++ b/src/views/offering/UpdateOfferingAccess.vue
@@ -0,0 +1,294 @@
+// 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 class="form-layout">
+ <a-spin :spinning="loading">
+ <a-form
+ :form="form"
+ @submit="handleSubmit"
+ layout="vertical">
+
+ <a-form-item :label="$t('ispublic')" v-show="this.isAdmin()">
+ <a-switch v-decorator="['ispublic']" :checked="this.offeringIsPublic" @change="val => { this.offeringIsPublic = val }" />
+ </a-form-item>
+
+ <a-form-item :label="$t('domainid')" v-if="!this.offeringIsPublic">
+ <a-select
+ mode="multiple"
+ v-decorator="['domainid', {
+ rules: [
+ {
+ required: true,
+ message: 'Please select option'
+ }
+ ]
+ }]"
+ showSearch
+ optionFilterProp="children"
+ :filterOption="(input, option) => {
+ return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }"
+ :loading="domainLoading"
+ :placeholder="this.$t('label.domain')">
+ <a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
+ {{ opt.name || opt.description }}
+ </a-select-option>
+ </a-select>
+ </a-form-item>
+
+ <a-form-item :label="$t('zoneid')">
+ <a-select
+ id="zone-selection"
+ mode="multiple"
+ v-decorator="['zoneid', {
+ rules: [
+ {
+ validator: (rule, value, callback) => {
+ if (value && value.length > 1 && value.indexOf(0) !== -1) {
+ callback('All Zones cannot be combined with any other zone')
+ }
+ callback()
+ }
+ }
+ ]
+ }]"
+ showSearch
+ optionFilterProp="children"
+ :filterOption="(input, option) => {
+ return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }"
+ :loading="zoneLoading"
+ :placeholder="this.$t('label.zone')">
+ <a-select-option v-for="(opt, optIndex) in this.zones" :key="optIndex">
+ {{ opt.name || opt.description }}
+ </a-select-option>
+ </a-select>
+ </a-form-item>
+
+ <div :span="24" class="action-button">
+ <a-button @click="closeAction">{{ this.$t('Cancel') }}</a-button>
+ <a-button :loading="loading" type="primary" @click="handleSubmit">{{ this.$t('OK') }}</a-button>
+ </div>
+
+ </a-form>
+ </a-spin>
+ </div>
+</template>
+
+<script>
+import { api } from '@/api'
+
+export default {
+ name: 'UpdateOfferingAccess',
+ props: {
+ resource: {
+ type: Object,
+ required: true
+ }
+ },
+ data () {
+ return {
+ offeringType: '',
+ selectedDomains: [],
+ selectedZones: [],
+ offeringIsPublic: false,
+ domains: [],
+ domainLoading: false,
+ zones: [],
+ zoneLoading: false,
+ loading: false
+ }
+ },
+ beforeCreate () {
+ this.form = this.$form.createForm(this)
+ },
+ created () {
+ this.zones = [
+ {
+ id: 'all',
+ name: this.$t('label.all.zone')
+ }
+ ]
+ },
+ mounted () {
+ this.offeringType = this.$route.meta.name
+ switch (this.$route.meta.name) {
+ case 'computeoffering':
+ this.offeringType = 'ServiceOffering'
+ break
+ case 'diskoffering':
+ this.offeringType = 'DiskOffering'
+ break
+ case 'networkoffering':
+ this.offeringType = 'NetworkOffering'
+ break
+ case 'vpcoffering':
+ this.offeringType = 'VPCOffering'
+ break
+ default:
+ this.offeringType = this.$route.meta.name
+ }
+ this.fetchData()
+ },
+ methods: {
+ fetchData () {
+ this.fetchDomainData()
+ this.fetchZoneData()
+ },
+ isAdmin () {
+ return ['Admin'].includes(this.$store.getters.userInfo.roletype)
+ },
+ fetchDomainData () {
+ const params = {}
+ params.listAll = true
+ params.details = 'min'
+ this.domainLoading = true
+ api('listDomains', params).then(json => {
+ const listDomains = json.listdomainsresponse.domain
+ this.domains = this.domains.concat(listDomains)
+ }).finally(() => {
+ this.domainLoading = false
+ })
+ },
+ fetchZoneData () {
+ const params = {}
+ params.listAll = true
+ this.zoneLoading = true
+ api('listZones', params).then(json => {
+ const listZones = json.listzonesresponse.zone
+ this.zones = this.zones.concat(listZones)
+ }).finally(() => {
+ this.zoneLoading = false
+ })
+ },
+ updateDomainSelection () {
+ var offeringDomainIds = this.resource.domainid
+ this.selectedDomains = []
+ if (offeringDomainIds) {
+ this.offeringIsPublic = false
+ offeringDomainIds = offeringDomainIds.indexOf(',') !== -1 ? offeringDomainIds.split(',') : [offeringDomainIds]
+ for (var i = 0; i < offeringDomainIds.length; i++) {
+ for (var j = 0; j < this.domains.length; j++) {
+ if (offeringDomainIds[i] === this.domains[j].id) {
+ this.selectedDomains = this.selectedDomains.concat(j)
+ }
+ }
+ }
+ } else {
+ if (this.isAdmin()) {
+ this.offeringIsPublic = true
+ }
+ }
+ this.form.setFieldsValue({
+ domainid: this.selectedDomains
+ })
+ },
+ updateZoneSelection () {
+ var offeringZoneIds = this.resource.zoneid
+ this.selectedZones = []
+ if (offeringZoneIds) {
+ offeringZoneIds = offeringZoneIds.indexOf(',') !== -1 ? offeringZoneIds.split(',') : [offeringZoneIds]
+ for (var i = 0; i < offeringZoneIds.length; i++) {
+ for (var j = 0; j < this.zones.length; j++) {
+ if (offeringZoneIds[i] === this.zones[j].id) {
+ this.selectedZones = this.selectedZones.concat(j)
+ }
+ }
+ }
+ }
+ this.form.setFieldsValue({
+ zoneid: this.selectedZones
+ })
+ },
+ handleSubmit (e) {
+ e.preventDefault()
+ this.form.validateFields((err, values) => {
+ if (err) {
+ return
+ }
+
+ const params = {}
+ params.id = this.resource.id
+ var ispublic = values.ispublic
+ if (ispublic === true) {
+ params.domainid = 'public'
+ } else {
+ var domainIndexes = values.domainid
+ var domainId = 'public'
+ if (domainIndexes && domainIndexes.length > 0) {
+ var domainIds = []
+ for (var i = 0; i < domainIndexes.length; i++) {
+ domainIds = domainIds.concat(this.domains[domainIndexes[i]].id)
+ }
+ domainId = domainIds.join(',')
+ }
+ params.domainid = domainId
+ }
+ var zoneIndexes = values.zoneid
+ var zoneId = 'all'
+ if (zoneIndexes && zoneIndexes.length > 0) {
+ var zoneIds = []
+ for (var j = 0; j < zoneIndexes.length; j++) {
+ zoneIds = zoneIds.concat(this.zones[zoneIndexes[j]].id)
+ }
+ zoneId = zoneIds.join(',')
+ }
+ params.zoneid = zoneId
+
+ this.loading = true
+ api('update' + this.offeringType, params).then(json => {
+ this.$emit('refresh-data')
+ this.$notification.success({
+ message: this.$t('label.action.update.offering.access'),
+ description: this.$t('label.action.update.offering.access')
+ })
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
+ })
+ }).finally(() => {
+ this.loading = false
+ this.closeAction()
+ })
+ })
+ },
+ closeAction () {
+ this.$emit('close-action')
+ }
+ }
+}
+</script>
+
+<style scoped lang="scss">
+ .form-layout {
+ width: 80vw;
+
+ @media (min-width: 1000px) {
+ width: 35vw;
+ }
+ }
+
+ .action-button {
+ text-align: right;
+
+ button {
+ margin-right: 5px;
+ }
+ }
+</style>