mirror of https://github.com/apache/cloudstack.git
src: Consolidated Bug fixes (#539)
Fixes : - Don't allow users in UI to delete/archive events - Fix button name in VM deployment form in its network section to Create new network - Refresh after template / iso upload - Making external-id mandatory in ImportBackupOffering - Fixing visibility of assignVirtualMachineToBackupOffering - Removing link on traffic label - Defensive check in TrafficTypesTab - Ensuring we get the user info so that store.getters.user is never empty when the page is freshly loaded - Changing from report bug to report issue - Ordering projects in menu - Changing router get health check results - Show configureHAForHost based on hypervisor - Fix scale and migrate router - Fix scale and migrate systemvm - Fix show actionbutton for assignVirtualMachineToBackupOffering - Fix show actionbutton for stopKubernetesCluster - Fix show actions for volumes - Fix show actions for snapshots - Fix show actions for vm snapshots - Fix show actions for backups - Adding loading for tags and annotations - Enter to submit advanced search - Fixing show Project instead of account when passed as projectaccount passed in account field - Show project name instead of displaytext - Fixing template and iso actions - Fixing tags with projectid - Fix security groups ingress/egress rules view - Removing redundant allocationstate from zones - Adding managedstate to clusters - Adding capacity tab to clusters and pods - Adding routerlink to events in dashboard - Set autofocus to username in login Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
e2e638e7a6
commit
6f0522eaed
|
|
@ -48,6 +48,7 @@
|
|||
<script>
|
||||
import store from '@/store'
|
||||
import { api } from '@/api'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'ProjectMenu',
|
||||
|
|
@ -66,20 +67,20 @@ export default {
|
|||
return
|
||||
}
|
||||
var page = 1
|
||||
const projects = []
|
||||
const getNextPage = () => {
|
||||
this.loading = true
|
||||
api('listProjects', { listAll: true, details: 'min', page: page, pageSize: 500 }).then(json => {
|
||||
if (page === 1) {
|
||||
this.projects = [{ name: this.$t('label.default.view') }]
|
||||
}
|
||||
if (json && json.listprojectsresponse && json.listprojectsresponse.project) {
|
||||
this.projects.push(...json.listprojectsresponse.project)
|
||||
projects.push(...json.listprojectsresponse.project)
|
||||
}
|
||||
if (this.projects.length - 1 < json.listprojectsresponse.count) {
|
||||
if (projects.length < json.listprojectsresponse.count) {
|
||||
page++
|
||||
getNextPage()
|
||||
}
|
||||
}).finally(() => {
|
||||
this.projects = _.orderBy(projects, ['displaytext'], ['asc'])
|
||||
this.projects.unshift({ name: this.$t('label.default.view') })
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
|
|
@ -92,7 +93,7 @@ export default {
|
|||
const project = this.projects[index]
|
||||
this.$store.dispatch('SetProject', project)
|
||||
this.$store.dispatch('ToggleTheme', project.id === undefined ? 'light' : 'dark')
|
||||
this.$message.success(`Switched to "${project.name}"`)
|
||||
this.$message.success(`Switched to "${project.displaytext}"`)
|
||||
if (this.$route.name !== 'dashboard') {
|
||||
this.$router.push({ name: 'dashboard' })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
:count="actionBadge[action.api] ? actionBadge[action.api].badgeNum : 0"
|
||||
v-if="action.api in $store.getters.apis &&
|
||||
action.showBadge && (
|
||||
(!dataView && (action.listView || (action.groupAction && selectedRowKeys.length > 0))) ||
|
||||
(!dataView && (action.listView || (action.groupAction && selectedRowKeys.length > 0 && ('groupShow' in action ? action.show(resource, $store.getters) : true)))) ||
|
||||
(dataView && action.dataView && ('show' in action ? action.show(resource, $store.getters) : true))
|
||||
)" >
|
||||
<a-button
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
<a-button
|
||||
v-if="action.api in $store.getters.apis &&
|
||||
!action.showBadge && (
|
||||
(!dataView && (action.listView || (action.groupAction && selectedRowKeys.length > 0))) ||
|
||||
(!dataView && (action.listView || (action.groupAction && selectedRowKeys.length > 0 && ('groupShow' in action ? action.show(resource, $store.getters) : true)))) ||
|
||||
(dataView && action.dataView && ('show' in action ? action.show(resource, $store.getters) : true))
|
||||
)"
|
||||
:icon="action.icon"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<template>
|
||||
<a-list
|
||||
size="small"
|
||||
:dataSource="$route.meta.details">
|
||||
:dataSource="projectname ? [...$route.meta.details.filter(x => x !== 'account'), 'projectname'] : $route.meta.details">
|
||||
<a-list-item slot="renderItem" slot-scope="item" v-if="item in resource">
|
||||
<div>
|
||||
<strong>{{ item === 'service' ? $t('label.supportedservices') : $t('label.' + String(item).toLowerCase()) }}</strong>
|
||||
|
|
@ -73,7 +73,8 @@ export default {
|
|||
data () {
|
||||
return {
|
||||
dedicatedRoutes: ['zone', 'pod', 'cluster', 'host'],
|
||||
dedicatedSectionActive: false
|
||||
dedicatedSectionActive: false,
|
||||
projectname: ''
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
|
@ -83,6 +84,13 @@ export default {
|
|||
this.dedicatedSectionActive = this.dedicatedRoutes.includes(this.$route.meta.name)
|
||||
},
|
||||
watch: {
|
||||
resource (newItem) {
|
||||
this.resource = newItem
|
||||
if ('account' in this.resource && this.resource.account.startsWith('PrjAcct-')) {
|
||||
this.projectname = this.resource.account.substring(this.resource.account.indexOf('-') + 1, this.resource.account.lastIndexOf('-'))
|
||||
this.resource.projectname = this.projectname
|
||||
}
|
||||
},
|
||||
$route () {
|
||||
this.dedicatedSectionActive = this.dedicatedRoutes.includes(this.$route.meta.name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
|
||||
<a-divider/>
|
||||
|
||||
<div class="resource-detail-item" v-if="resource.state || resource.status">
|
||||
<div class="resource-detail-item" v-if="(resource.state || resource.status) && $route.meta.name !== 'zone'">
|
||||
<div class="resource-detail-item__label">{{ $t('label.status') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<status class="status" :text="resource.state || resource.status" displayText/>
|
||||
|
|
@ -288,11 +288,12 @@
|
|||
<span v-else>{{ resource.ipaddress }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.projectid">
|
||||
<div class="resource-detail-item" v-if="resource.projectid || resource.projectname">
|
||||
<div class="resource-detail-item__label">{{ $t('label.project') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<a-icon type="project" />
|
||||
<router-link :to="{ path: '/project/' + resource.projectid }">{{ resource.project || resource.projectname || resource.projectid }}</router-link>
|
||||
<router-link v-if="resource.projectid" :to="{ path: '/project/' + resource.projectid }">{{ resource.project || resource.projectname || resource.projectid }}</router-link>
|
||||
<router-link v-else :to="{ path: '/project', query: { name: resource.projectname }}">{{ resource.projectname }}</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -458,7 +459,7 @@
|
|||
<span v-else>{{ resource.zone || resource.zonename || resource.zoneid }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.account">
|
||||
<div class="resource-detail-item" v-if="resource.account && !resource.account.startsWith('PrjAcct-')">
|
||||
<div class="resource-detail-item__label">{{ $t('label.account') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<a-icon type="user" />
|
||||
|
|
@ -551,88 +552,89 @@
|
|||
|
||||
<div class="account-center-tags" v-if="resourceType && 'listTags' in $store.getters.apis">
|
||||
<a-divider/>
|
||||
<div class="title">{{ $t('label.tags') }}</div>
|
||||
<div>
|
||||
<template v-for="(tag, index) in tags">
|
||||
<a-tag :key="index" :closable="'deleteTags' in $store.getters.apis" :afterClose="() => handleDeleteTag(tag)">
|
||||
{{ tag.key }} = {{ tag.value }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<a-spin :spinning="loadingTags">
|
||||
<div class="title">{{ $t('label.tags') }}</div>
|
||||
<div>
|
||||
<template v-for="(tag, index) in tags">
|
||||
<a-tag :key="index" :closable="isAdminOrOwner() && 'deleteTags' in $store.getters.apis" :afterClose="() => handleDeleteTag(tag)">
|
||||
{{ tag.key }} = {{ tag.value }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<div v-if="inputVisible">
|
||||
<a-input-group
|
||||
type="text"
|
||||
size="small"
|
||||
@blur="handleInputConfirm"
|
||||
@keyup.enter="handleInputConfirm"
|
||||
compact>
|
||||
<a-input ref="input" :value="inputKey" @change="handleKeyChange" style="width: 30%; text-align: center" :placeholder="$t('label.key')" />
|
||||
<a-input style=" width: 30px; border-left: 0; pointer-events: none; backgroundColor: #fff" placeholder="=" disabled />
|
||||
<a-input :value="inputValue" @change="handleValueChange" style="width: 30%; text-align: center; border-left: 0" :placeholder="$t('label.value')" />
|
||||
<a-button shape="circle" size="small" @click="handleInputConfirm">
|
||||
<a-icon type="check"/>
|
||||
</a-button>
|
||||
<a-button shape="circle" size="small" @click="inputVisible=false">
|
||||
<a-icon type="close"/>
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<div v-if="inputVisible">
|
||||
<a-input-group
|
||||
type="text"
|
||||
size="small"
|
||||
@blur="handleInputConfirm"
|
||||
@keyup.enter="handleInputConfirm"
|
||||
compact>
|
||||
<a-input ref="input" :value="inputKey" @change="handleKeyChange" style="width: 30%; text-align: center" :placeholder="$t('label.key')" />
|
||||
<a-input style=" width: 30px; border-left: 0; pointer-events: none; backgroundColor: #fff" placeholder="=" disabled />
|
||||
<a-input :value="inputValue" @change="handleValueChange" style="width: 30%; text-align: center; border-left: 0" :placeholder="$t('label.value')" />
|
||||
<a-button shape="circle" size="small" @click="handleInputConfirm">
|
||||
<a-icon type="check"/>
|
||||
</a-button>
|
||||
<a-button shape="circle" size="small" @click="inputVisible=false">
|
||||
<a-icon type="close"/>
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
</div>
|
||||
<a-tag @click="showInput" style="background: #fff; borderStyle: dashed;" v-else-if="isAdminOrOwner() && 'createTags' in $store.getters.apis">
|
||||
<a-icon type="plus" /> {{ $t('label.new.tag') }}
|
||||
</a-tag>
|
||||
</div>
|
||||
<a-tag @click="showInput" style="background: #fff; borderStyle: dashed;" v-else-if="'createTags' in $store.getters.apis">
|
||||
<a-icon type="plus" /> {{ $t('label.new.tag') }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</a-spin>
|
||||
</div>
|
||||
|
||||
<div class="account-center-team" v-if="annotationType && 'listAnnotations' in $store.getters.apis">
|
||||
<a-divider :dashed="true"/>
|
||||
<div class="title">
|
||||
{{ $t('label.comments') }} ({{ notes.length }})
|
||||
</div>
|
||||
<a-list
|
||||
v-if="notes.length"
|
||||
:dataSource="notes"
|
||||
itemLayout="horizontal"
|
||||
size="small"
|
||||
>
|
||||
<a-list-item slot="renderItem" slot-scope="item">
|
||||
<a-comment
|
||||
:content="item.annotation"
|
||||
:datetime="item.created"
|
||||
>
|
||||
<a-button
|
||||
v-if="'removeAnnotation' in $store.getters.apis"
|
||||
slot="avatar"
|
||||
type="danger"
|
||||
shape="circle"
|
||||
size="small"
|
||||
@click="deleteNote(item)">
|
||||
<a-icon type="delete"/>
|
||||
</a-button>
|
||||
</a-comment>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
|
||||
<a-comment v-if="'addAnnotation' in $store.getters.apis">
|
||||
<a-avatar
|
||||
slot="avatar"
|
||||
icon="edit"
|
||||
@click="showNotesInput = true"
|
||||
/>
|
||||
<div slot="content">
|
||||
<a-textarea
|
||||
rows="4"
|
||||
@change="handleNoteChange"
|
||||
:value="annotation"
|
||||
:placeholder="$t('label.add.note')" />
|
||||
<a-button
|
||||
style="margin-top: 10px"
|
||||
@click="saveNote"
|
||||
type="primary"
|
||||
>
|
||||
{{ $t('label.save') }}
|
||||
</a-button>
|
||||
<a-spin :spinning="loadingAnnotations">
|
||||
<div class="title">
|
||||
{{ $t('label.comments') }} ({{ notes.length }})
|
||||
</div>
|
||||
</a-comment>
|
||||
<a-list
|
||||
v-if="notes.length"
|
||||
:dataSource="notes"
|
||||
itemLayout="horizontal"
|
||||
size="small" >
|
||||
<a-list-item slot="renderItem" slot-scope="item">
|
||||
<a-comment
|
||||
:content="item.annotation"
|
||||
:datetime="item.created" >
|
||||
<a-button
|
||||
v-if="'removeAnnotation' in $store.getters.apis"
|
||||
slot="avatar"
|
||||
type="danger"
|
||||
shape="circle"
|
||||
size="small"
|
||||
@click="deleteNote(item)">
|
||||
<a-icon type="delete"/>
|
||||
</a-button>
|
||||
</a-comment>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
|
||||
<a-comment v-if="'addAnnotation' in $store.getters.apis">
|
||||
<a-avatar
|
||||
slot="avatar"
|
||||
icon="edit"
|
||||
@click="showNotesInput = true" />
|
||||
<div slot="content">
|
||||
<a-textarea
|
||||
rows="4"
|
||||
@change="handleNoteChange"
|
||||
:value="annotation"
|
||||
:placeholder="$t('label.add.note')" />
|
||||
<a-button
|
||||
style="margin-top: 10px"
|
||||
@click="saveNote"
|
||||
type="primary"
|
||||
>
|
||||
{{ $t('label.save') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-comment>
|
||||
</a-spin>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-spin>
|
||||
|
|
@ -681,7 +683,9 @@ export default {
|
|||
notes: [],
|
||||
annotation: '',
|
||||
showKeys: false,
|
||||
showNotesInput: false
|
||||
showNotesInput: false,
|
||||
loadingTags: false,
|
||||
loadingAnnotations: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -746,6 +750,7 @@ export default {
|
|||
if (!('listTags' in this.$store.getters.apis) || !this.resource || !this.resource.id) {
|
||||
return
|
||||
}
|
||||
this.loadingTags = true
|
||||
this.tags = []
|
||||
const params = {
|
||||
listall: true,
|
||||
|
|
@ -759,19 +764,29 @@ export default {
|
|||
if (json.listtagsresponse && json.listtagsresponse.tag) {
|
||||
this.tags = json.listtagsresponse.tag
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loadingTags = false
|
||||
})
|
||||
},
|
||||
getNotes () {
|
||||
if (!('listAnnotations' in this.$store.getters.apis)) {
|
||||
return
|
||||
}
|
||||
this.loadingAnnotations = true
|
||||
this.notes = []
|
||||
api('listAnnotations', { entityid: this.resource.id, entitytype: this.annotationType }).then(json => {
|
||||
if (json.listannotationsresponse && json.listannotationsresponse.annotation) {
|
||||
this.notes = json.listannotationsresponse.annotation
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loadingAnnotations = false
|
||||
})
|
||||
},
|
||||
isAdminOrOwner () {
|
||||
return ['Admin'].includes(this.$store.getters.userInfo.roletype) ||
|
||||
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account) ||
|
||||
this.resource.project && this.resource.projectid === this.$store.getters.project.id
|
||||
},
|
||||
showInput () {
|
||||
this.inputVisible = true
|
||||
this.$nextTick(function () {
|
||||
|
|
@ -786,6 +801,7 @@ export default {
|
|||
},
|
||||
handleInputConfirm () {
|
||||
const args = {}
|
||||
this.loadingTags = true
|
||||
args.resourceids = this.resource.id
|
||||
args.resourcetype = this.resourceType
|
||||
args['tags[0].key'] = this.inputKey
|
||||
|
|
@ -801,6 +817,7 @@ export default {
|
|||
},
|
||||
handleDeleteTag (tag) {
|
||||
const args = {}
|
||||
this.loadingTags = true
|
||||
args.resourceids = this.resource.id
|
||||
args.resourcetype = this.resourceType
|
||||
args['tags[0].key'] = tag.key
|
||||
|
|
@ -817,6 +834,7 @@ export default {
|
|||
if (this.annotation.length < 1) {
|
||||
return
|
||||
}
|
||||
this.loadingAnnotations = true
|
||||
this.showNotesInput = false
|
||||
const args = {}
|
||||
args.entityid = this.resource.id
|
||||
|
|
@ -829,6 +847,7 @@ export default {
|
|||
this.annotation = ''
|
||||
},
|
||||
deleteNote (annotation) {
|
||||
this.loadingAnnotations = true
|
||||
const args = {}
|
||||
args.id = annotation.id
|
||||
api('removeAnnotation', args).then(json => {
|
||||
|
|
|
|||
|
|
@ -104,9 +104,9 @@
|
|||
<a slot="publicip" slot-scope="text, record" href="javascript:;">
|
||||
<router-link :to="{ path: $route.path + '/' + record.id }">{{ text }}</router-link>
|
||||
</a>
|
||||
<a slot="traffictype" slot-scope="text, record" href="javascript:;">
|
||||
<router-link :to="{ path: $route.path + '/' + record.id + '?physicalnetworkid=' + record.physicalnetworkid }">{{ text }}</router-link>
|
||||
</a>
|
||||
<span slot="traffictype" slot-scope="text" href="javascript:;">
|
||||
{{ text }}
|
||||
</span>
|
||||
<a slot="vmname" slot-scope="text, record" href="javascript:;">
|
||||
<router-link :to="{ path: '/vm/' + record.virtualmachineid }">{{ text }}</router-link>
|
||||
</a>
|
||||
|
|
@ -164,12 +164,14 @@
|
|||
<router-link :to="{ path: '/pod/' + record.podid }">{{ text }}</router-link>
|
||||
</a>
|
||||
<span slot="account" slot-scope="text, record">
|
||||
<router-link
|
||||
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>
|
||||
<span v-else>{{ text }}</span>
|
||||
<template v-if="text && !text.startsWith('PrjAcct-')">
|
||||
<router-link
|
||||
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>
|
||||
<span v-else>{{ text }}</span>
|
||||
</template>
|
||||
</span>
|
||||
<span slot="domain" slot-scope="text, record" href="javascript:;">
|
||||
<router-link v-if="record.domainid && !record.domainid.toString().includes(',') && $store.getters.userInfo.roletype !== 'User'" :to="{ path: '/domain/' + record.domainid }">{{ text }}</router-link>
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@
|
|||
type="primary"
|
||||
size="small"
|
||||
icon="search"
|
||||
html-type="submit"
|
||||
@click="handleSubmit">{{ $t('label.search') }}</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ export default {
|
|||
docHelp: 'adminguide/virtual_machines.html#backup-offerings',
|
||||
dataView: true,
|
||||
args: ['virtualmachineid', 'backupofferingid'],
|
||||
show: (record) => { return !record.backupofferingid && !['Error', 'Destroyed'].includes(record.state) && ['VMware', 'Simulator'].includes(record.hypervisor) },
|
||||
show: (record) => { return !record.backupofferingid },
|
||||
mapping: {
|
||||
virtualmachineid: {
|
||||
value: (record, params) => { return record.id }
|
||||
|
|
@ -441,7 +441,7 @@ export default {
|
|||
label: 'label.kubernetes.cluster.stop',
|
||||
docHelp: 'plugins/cloudstack-kubernetes-service.html#stopping-kubernetes-cluster',
|
||||
dataView: true,
|
||||
show: (record) => { return !['Stopped'].includes(record.state) }
|
||||
show: (record) => { return !['Stopped', 'Destroyed', 'Destroying'].includes(record.state) }
|
||||
},
|
||||
{
|
||||
api: 'scaleKubernetesCluster',
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ export default {
|
|||
ids: {
|
||||
value: (record) => { return record.id }
|
||||
}
|
||||
}
|
||||
},
|
||||
show: (record, store) => { return !['User'].includes(store.userInfo.roletype) },
|
||||
groupShow: (record, store) => { return !['User'].includes(store.userInfo.roletype) }
|
||||
},
|
||||
{
|
||||
api: 'deleteEvents',
|
||||
|
|
@ -60,7 +62,9 @@ export default {
|
|||
ids: {
|
||||
value: (record) => { return record.id }
|
||||
}
|
||||
}
|
||||
},
|
||||
show: (record, store) => { return !['User'].includes(store.userInfo.roletype) },
|
||||
groupShow: (record, store) => { return !['User'].includes(store.userInfo.roletype) }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,8 +85,9 @@ export default {
|
|||
label: 'label.edit',
|
||||
dataView: true,
|
||||
show: (record, store) => {
|
||||
return (['Admin'].includes(store.userInfo.roletype) ||
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account)) &&
|
||||
return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) ||
|
||||
(record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) &&
|
||||
record.templatetype !== 'SYSTEM' &&
|
||||
record.isready
|
||||
},
|
||||
|
|
@ -105,8 +106,9 @@ export default {
|
|||
dataView: true,
|
||||
args: ['ispublic', 'isfeatured', 'isextractable'],
|
||||
show: (record, store) => {
|
||||
return (['Admin'].includes(store.userInfo.roletype) ||
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account)) &&
|
||||
return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) ||
|
||||
(record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) &&
|
||||
record.templatetype !== 'SYSTEM' &&
|
||||
record.isready
|
||||
}
|
||||
|
|
@ -119,8 +121,9 @@ export default {
|
|||
docHelp: 'adminguide/templates.html#exporting-templates',
|
||||
dataView: true,
|
||||
show: (record, store) => {
|
||||
return (['Admin'].includes(store.userInfo.roletype) ||
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account)) &&
|
||||
return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) ||
|
||||
(record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) &&
|
||||
record.templatetype !== 'SYSTEM' &&
|
||||
record.isready &&
|
||||
record.isextractable
|
||||
|
|
@ -144,8 +147,9 @@ export default {
|
|||
dataView: true,
|
||||
popup: true,
|
||||
show: (record, store) => {
|
||||
return (['Admin'].includes(store.userInfo.roletype) ||
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account)) &&
|
||||
return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) ||
|
||||
(record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) &&
|
||||
record.templatetype !== 'SYSTEM' &&
|
||||
record.isready
|
||||
},
|
||||
|
|
@ -208,9 +212,10 @@ export default {
|
|||
label: 'label.action.edit.iso',
|
||||
dataView: true,
|
||||
show: (record, store) => {
|
||||
return (['Admin'].includes(store.userInfo.roletype) ||
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account)) &&
|
||||
!(record.account === 'SYSTEM' && record.domainid === 1) &&
|
||||
return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) ||
|
||||
(record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) &&
|
||||
!(record.account === 'system' && record.domainid === 1) &&
|
||||
record.isready
|
||||
},
|
||||
args: ['name', 'displaytext', 'bootable', 'ostypeid']
|
||||
|
|
@ -222,9 +227,10 @@ export default {
|
|||
dataView: true,
|
||||
args: ['ispublic', 'isfeatured', 'isextractable'],
|
||||
show: (record, store) => {
|
||||
return (['Admin'].includes(store.userInfo.roletype) ||
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account)) &&
|
||||
!(record.account === 'SYSTEM' && record.domainid === 1) &&
|
||||
return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) ||
|
||||
(record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) &&
|
||||
!(record.account === 'system' && record.domainid === 1) &&
|
||||
record.isready
|
||||
}
|
||||
},
|
||||
|
|
@ -236,9 +242,10 @@ export default {
|
|||
docHelp: 'adminguide/templates.html#exporting-templates',
|
||||
dataView: true,
|
||||
show: (record, store) => {
|
||||
return (['Admin'].includes(store.userInfo.roletype) ||
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account)) &&
|
||||
!(record.account === 'SYSTEM' && record.domainid === 1) &&
|
||||
return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) ||
|
||||
(record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) &&
|
||||
!(record.account === 'system' && record.domainid === 1) &&
|
||||
record.isready
|
||||
},
|
||||
args: ['zoneid', 'mode'],
|
||||
|
|
@ -261,9 +268,10 @@ export default {
|
|||
args: ['op', 'accounts', 'projectids'],
|
||||
popup: true,
|
||||
show: (record, store) => {
|
||||
return (['Admin'].includes(store.userInfo.roletype) ||
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account)) &&
|
||||
!(record.account === 'SYSTEM' && record.domainid === 1) &&
|
||||
return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) ||
|
||||
(record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) &&
|
||||
!(record.account === 'system' && record.domainid === 1) &&
|
||||
record.isready
|
||||
},
|
||||
component: () => import('@/views/image/UpdateTemplateIsoPermissions')
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export default {
|
|||
fields.push('zonename')
|
||||
return fields
|
||||
},
|
||||
details: ['name', 'id', 'allocationstate', 'clustertype', 'hypervisortype', 'podname', 'zonename'],
|
||||
details: ['name', 'id', 'allocationstate', 'clustertype', 'managedstate', 'hypervisortype', 'podname', 'zonename'],
|
||||
related: [{
|
||||
name: 'host',
|
||||
title: 'label.hosts',
|
||||
|
|
@ -44,6 +44,9 @@ export default {
|
|||
}, {
|
||||
name: 'settings',
|
||||
component: () => import('@/components/view/SettingsTab.vue')
|
||||
}, {
|
||||
name: 'resources',
|
||||
component: () => import('@/views/infra/Resources.vue')
|
||||
}],
|
||||
actions: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ export default {
|
|||
message: 'label.ha.configure',
|
||||
docHelp: 'adminguide/reliability.html#ha-for-hosts',
|
||||
dataView: true,
|
||||
show: (record) => { return ['KVM', 'Simulator'].includes(record.hypervisor) },
|
||||
args: ['hostid', 'provider'],
|
||||
mapping: {
|
||||
hostid: {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,13 @@ export default {
|
|||
title: 'label.hosts',
|
||||
param: 'podid'
|
||||
}],
|
||||
tabs: [{
|
||||
name: 'details',
|
||||
component: () => import('@/components/view/DetailsTab.vue')
|
||||
}, {
|
||||
name: 'resources',
|
||||
component: () => import('@/views/infra/Resources.vue')
|
||||
}],
|
||||
actions: [
|
||||
{
|
||||
api: 'createPod',
|
||||
|
|
|
|||
|
|
@ -103,6 +103,10 @@ export default {
|
|||
mapping: {
|
||||
virtualmachineid: {
|
||||
value: (record) => { return record.id }
|
||||
},
|
||||
hostid: {
|
||||
api: 'findHostsForMigration',
|
||||
params: (record) => { return { virtualmachineid: record.id } }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -55,12 +55,12 @@ export default {
|
|||
label: 'label.change.service.offering',
|
||||
message: 'message.confirm.scale.up.system.vm',
|
||||
dataView: true,
|
||||
show: (record) => { return record.hypervisor !== 'KVM' },
|
||||
show: (record) => { return record.state === 'Running' && record.hypervisor === 'VMware' || record.state === 'Stopped' },
|
||||
args: ['serviceofferingid'],
|
||||
mapping: {
|
||||
serviceofferingid: {
|
||||
api: 'listServiceOfferings',
|
||||
params: (record) => { return { virtualmachineid: record.virtualmachineid, issystem: true, systemvmtype: record.systemvmtype } }
|
||||
params: (record) => { return { virtualmachineid: record.id, issystem: true, systemvmtype: record.systemvmtype } }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -74,6 +74,10 @@ export default {
|
|||
mapping: {
|
||||
virtualmachineid: {
|
||||
value: (record) => { return record.id }
|
||||
},
|
||||
hostid: {
|
||||
api: 'findHostsForMigration',
|
||||
params: (record) => { return { virtualmachineid: record.id } }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default {
|
|||
icon: 'global',
|
||||
permission: ['listZonesMetrics'],
|
||||
columns: () => {
|
||||
const fields = ['name', 'state', 'allocationstate', 'networktype', 'clusters']
|
||||
const fields = ['name', 'allocationstate', 'networktype', 'clusters']
|
||||
const metricsFields = ['cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal']
|
||||
if (store.getters.metrics) {
|
||||
fields.push(...metricsFields)
|
||||
|
|
@ -64,7 +64,7 @@ export default {
|
|||
component: () => import('@/views/infra/zone/SystemVmsTab.vue')
|
||||
}, {
|
||||
name: 'resources',
|
||||
component: () => import('@/views/infra/zone/ZoneResources.vue')
|
||||
component: () => import('@/views/infra/Resources.vue')
|
||||
}, {
|
||||
name: 'settings',
|
||||
component: () => import('@/components/view/SettingsTab.vue')
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export default {
|
|||
message: 'message.confirm.attach.disk',
|
||||
args: ['virtualmachineid'],
|
||||
dataView: true,
|
||||
show: (record) => { return record.type !== 'ROOT' && record.state !== 'Destroy' && !('virtualmachineid' in record) }
|
||||
show: (record) => { return record.type !== 'ROOT' && ['Allocated', 'Ready', 'Uploaded'].includes(record.state) && !('virtualmachineid' in record) }
|
||||
},
|
||||
{
|
||||
api: 'detachVolume',
|
||||
|
|
@ -110,7 +110,10 @@ export default {
|
|||
label: 'label.action.detach.disk',
|
||||
message: 'message.detach.disk',
|
||||
dataView: true,
|
||||
show: (record) => { return record.type !== 'ROOT' && 'virtualmachineid' in record && record.virtualmachineid }
|
||||
show: (record) => {
|
||||
return record.type !== 'ROOT' && 'virtualmachineid' in record && record.virtualmachineid &&
|
||||
['Running', 'Stopped', 'Destroyed'].includes(record.vmstate)
|
||||
}
|
||||
},
|
||||
{
|
||||
api: 'createSnapshot',
|
||||
|
|
@ -147,7 +150,7 @@ export default {
|
|||
label: 'label.action.resize.volume',
|
||||
dataView: true,
|
||||
popup: true,
|
||||
show: (record) => { return record.state !== 'Destroy' },
|
||||
show: (record) => { return ['Allocated', 'Ready'].includes(record.state) },
|
||||
component: () => import('@/views/storage/ResizeVolume.vue')
|
||||
},
|
||||
{
|
||||
|
|
@ -167,7 +170,7 @@ export default {
|
|||
label: 'label.action.download.volume',
|
||||
message: 'message.download.volume.confirm',
|
||||
dataView: true,
|
||||
show: (record) => { return record && record.state === 'Ready' && (record.vmstate === 'Stopped' || record.virtualmachineid == null) && record.state !== 'Destroy' },
|
||||
show: (record) => { return record && record.state === 'Ready' && (record.vmstate === 'Stopped' || record.virtualmachineid == null) },
|
||||
args: ['zoneid', 'mode'],
|
||||
mapping: {
|
||||
zoneid: {
|
||||
|
|
@ -278,14 +281,15 @@ export default {
|
|||
label: 'label.action.revert.snapshot',
|
||||
message: 'message.action.revert.snapshot',
|
||||
dataView: true,
|
||||
show: (record) => { return record.revertable }
|
||||
show: (record) => { return record.state === 'BackedUp' && record.revertable }
|
||||
},
|
||||
{
|
||||
api: 'deleteSnapshot',
|
||||
icon: 'delete',
|
||||
label: 'label.action.delete.snapshot',
|
||||
message: 'message.action.delete.snapshot',
|
||||
dataView: true
|
||||
dataView: true,
|
||||
show: (record) => { return record.state !== 'Destroyed' }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -326,6 +330,7 @@ export default {
|
|||
label: 'label.action.vmsnapshot.delete',
|
||||
message: 'message.action.vmsnapshot.delete',
|
||||
dataView: true,
|
||||
show: (record) => { return ['Ready', 'Expunging', 'Error'].includes(record.state) },
|
||||
args: ['vmsnapshotid'],
|
||||
mapping: {
|
||||
vmsnapshotid: {
|
||||
|
|
@ -349,7 +354,8 @@ export default {
|
|||
docHelp: 'adminguide/virtual_machines.html#restoring-vm-backups',
|
||||
label: 'label.backup.restore',
|
||||
message: 'message.backup.restore',
|
||||
dataView: true
|
||||
dataView: true,
|
||||
show: (record) => { return record.state !== 'Destroyed' }
|
||||
},
|
||||
{
|
||||
api: 'restoreVolumeFromBackupAndAttachToVM',
|
||||
|
|
@ -357,6 +363,7 @@ export default {
|
|||
label: 'label.backup.attach.restore',
|
||||
message: 'message.backup.attach.restore',
|
||||
dataView: true,
|
||||
show: (record) => { return record.state !== 'Destroyed' },
|
||||
popup: true,
|
||||
component: () => import('@/views/storage/RestoreAttachBackupVolume.vue')
|
||||
},
|
||||
|
|
@ -366,6 +373,7 @@ export default {
|
|||
label: 'label.backup.offering.remove',
|
||||
message: 'message.backup.offering.remove',
|
||||
dataView: true,
|
||||
show: (record) => { return record.state !== 'Destroyed' },
|
||||
args: ['forced', 'virtualmachineid'],
|
||||
mapping: {
|
||||
forced: {
|
||||
|
|
@ -381,7 +389,8 @@ export default {
|
|||
icon: 'delete',
|
||||
label: 'label.delete.backup',
|
||||
message: 'message.delete.backup',
|
||||
dataView: true
|
||||
dataView: true,
|
||||
show: (record) => { return record.state !== 'Destroyed' }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
"label.access": "Access",
|
||||
"label.accesskey": "Access Key",
|
||||
"label.account": "Account",
|
||||
"label.account.and.security.group": "Account, Security group",
|
||||
"label.account.and.security.group": "Account - Security group",
|
||||
"label.account.details": "Account details",
|
||||
"label.account.id": "Account ID",
|
||||
"label.account.name": "Account Name",
|
||||
|
|
@ -602,6 +602,7 @@
|
|||
"label.cpuusedghz": "Used CPU",
|
||||
"label.create.account": "Create Account",
|
||||
"label.create.backup": "Start Backup",
|
||||
"label.create.network": "Create New Network",
|
||||
"label.create.network.gateway.description": "The gateway of the tier in the super CIDR range and not overlapping the CIDR of any other tier in this VPC.",
|
||||
"label.create.network.netmask.description": "Netmask of the tier. For example, with VPC CIDR of 10.0.0.0/16 and network tier CIDR of 10.1.1.0/24, gateway is 10.1.1.1 and netmask is 255.255.255.0",
|
||||
"label.create.nfs.secondary.staging.storage": "Create NFS Secondary Staging Store",
|
||||
|
|
@ -1584,6 +1585,7 @@
|
|||
"label.profiledn": "Associated Profile",
|
||||
"label.profilename": "Profile",
|
||||
"label.project": "Project",
|
||||
"label.projectname": "Project",
|
||||
"label.project.dashboard": "Project dashboard",
|
||||
"label.project.ids": "Project IDs",
|
||||
"label.project.invitation": "Project Invitations",
|
||||
|
|
@ -1724,7 +1726,7 @@
|
|||
"label.removing.user": "Removing User",
|
||||
"label.replace.acl": "Replace ACL",
|
||||
"label.replace.acl.list": "Replace ACL List",
|
||||
"label.report.bug": "Report Bug",
|
||||
"label.report.bug": "Report Issue",
|
||||
"label.required": "Required",
|
||||
"label.requireshvm": "HVM",
|
||||
"label.requiresupgrade": "Requires Upgrade",
|
||||
|
|
|
|||
|
|
@ -123,7 +123,21 @@ const user = {
|
|||
if (hasAuth) {
|
||||
console.log('Login detected, using cached APIs')
|
||||
commit('SET_APIS', cachedApis)
|
||||
resolve(cachedApis)
|
||||
|
||||
// Ensuring we get the user info so that store.getters.user is never empty when the page is freshly loaded
|
||||
api('listUsers', { username: Cookies.get('username'), listall: true }).then(response => {
|
||||
const result = response.listusersresponse.user[0]
|
||||
commit('SET_INFO', result)
|
||||
commit('SET_NAME', result.firstname + ' ' + result.lastname)
|
||||
if ('email' in result) {
|
||||
commit('SET_AVATAR', 'https://www.gravatar.com/avatar/' + md5(result.email))
|
||||
} else {
|
||||
commit('SET_AVATAR', 'https://www.gravatar.com/avatar/' + md5('dev@cloudstack.apache.org'))
|
||||
}
|
||||
resolve(cachedApis)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
} else {
|
||||
const hide = message.loading(i18n.t('message.discovering.feature'), 0)
|
||||
api('listApis').then(response => {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,11 @@ service.interceptors.request.use(config => {
|
|||
config.params.response = 'json'
|
||||
const project = Vue.ls.get(CURRENT_PROJECT)
|
||||
if (!config.params.projectid && project && project.id) {
|
||||
config.params.projectid = project.id
|
||||
if (config.params.command === 'listTags') {
|
||||
config.params.projectid = '-1'
|
||||
} else {
|
||||
config.params.projectid = project.id
|
||||
}
|
||||
}
|
||||
}
|
||||
return config
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
<a-input
|
||||
size="large"
|
||||
type="text"
|
||||
autoFocus
|
||||
:placeholder="$t('label.username')"
|
||||
v-decorator="[
|
||||
'username',
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
v-model="filter"
|
||||
@search="handleSearch" />
|
||||
<a-button type="primary" @click="showCreateForm = true" style="float: right; margin-right: 5px; z-index: 8">
|
||||
{{ $t('label.add.network') }}
|
||||
{{ $t('label.create.network') }}
|
||||
</a-button>
|
||||
<a-table
|
||||
:loading="loading"
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@
|
|||
:key="event.id"
|
||||
:color="getEventColour(event)">
|
||||
<span :style="{ color: '#999' }"><small>{{ event.created }}</small></span><br/>
|
||||
<span :style="{ color: '#666' }"><small>{{ $t(event.type.toLowerCase()) }}</small></span><br/>
|
||||
<span :style="{ color: '#666' }"><small><router-link :to="{ path: 'event/' + event.id }">{{ event.type }}</router-link></small></span><br/>
|
||||
<span :style="{ color: '#aaa' }">({{ event.username }}) {{ event.description }}</span>
|
||||
</a-timeline-item>
|
||||
</a-timeline>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@
|
|||
:key="event.id"
|
||||
:color="getEventColour(event)">
|
||||
<span :style="{ color: '#999' }"><small>{{ event.created }}</small></span><br/>
|
||||
<span :style="{ color: '#666' }"><small>{{ event.type }}</small></span><br/>
|
||||
<span :style="{ color: '#666' }"><small><router-link :to="{ path: 'event/' + event.id }">{{ event.type }}</router-link></small></span><br/>
|
||||
<span :style="{ color: '#aaa' }">({{ event.username }}) {{ event.description }}</span>
|
||||
</a-timeline-item>
|
||||
</a-timeline>
|
||||
|
|
|
|||
|
|
@ -230,9 +230,11 @@ export default {
|
|||
this.fetchData()
|
||||
},
|
||||
isActionPermitted () {
|
||||
return (['Admin'].includes(this.$store.getters.userInfo.roletype) ||
|
||||
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account)) &&
|
||||
!(this.resource.account !== 'SYSTEM' && this.resource.domainid === 1)
|
||||
return (['Admin'].includes(this.$store.getters.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account) ||
|
||||
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.projectid && this.$store.getters.project && this.$store.getters.project.id && this.resource.projectid === this.$store.getters.project.id)) &&
|
||||
(this.resource.isready || !this.resource.status || this.resource.status.indexOf('Downloaded') === -1) && // Iso is ready or downloaded
|
||||
this.resource.account !== 'system'
|
||||
},
|
||||
deleteIso (record) {
|
||||
const params = {
|
||||
|
|
|
|||
|
|
@ -293,14 +293,15 @@ export default {
|
|||
message: this.$t('message.success.upload'),
|
||||
description: this.$t('message.success.upload.description')
|
||||
})
|
||||
this.closeAction()
|
||||
}).catch(e => {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.upload.failed'),
|
||||
description: `${this.$t('message.upload.iso.failed.description')} - ${e}`,
|
||||
duration: 0
|
||||
})
|
||||
}).finally(() => {
|
||||
this.closeAction()
|
||||
this.$emit('refresh-data')
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
|
|
@ -336,7 +337,6 @@ export default {
|
|||
if (this.currentForm === 'Create') {
|
||||
this.loading = true
|
||||
api('registerIso', params).then(json => {
|
||||
this.$emit('refresh-data')
|
||||
this.$notification.success({
|
||||
message: 'label.action.register.iso',
|
||||
description: `${this.$t('message.success.register.iso')} ${params.name}`
|
||||
|
|
@ -346,6 +346,7 @@ export default {
|
|||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.closeAction()
|
||||
this.$emit('refresh-data')
|
||||
})
|
||||
} else {
|
||||
if (this.fileList.length !== 1) {
|
||||
|
|
@ -366,6 +367,7 @@ export default {
|
|||
this.$notifyError(error)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.$emit('refresh-data')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -479,13 +479,14 @@ export default {
|
|||
message: this.$t('message.success.upload'),
|
||||
description: this.$t('message.success.upload.template.description')
|
||||
})
|
||||
this.closeAction()
|
||||
}).catch(e => {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.upload.failed'),
|
||||
description: `${this.$t('message.upload.template.failed.description')} - ${e}`,
|
||||
duration: 0
|
||||
})
|
||||
}).finally(() => {
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
})
|
||||
},
|
||||
|
|
@ -852,7 +853,6 @@ export default {
|
|||
if (this.currentForm === 'Create') {
|
||||
this.loading = true
|
||||
api('registerTemplate', params).then(json => {
|
||||
this.$emit('refresh-data')
|
||||
this.$notification.success({
|
||||
message: this.$t('label.register.template'),
|
||||
description: `${this.$t('message.success.register.template')} ${params.name}`
|
||||
|
|
@ -861,6 +861,7 @@ export default {
|
|||
this.$notifyError(error)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
})
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -240,9 +240,11 @@ export default {
|
|||
this.fetchData()
|
||||
},
|
||||
isActionPermitted () {
|
||||
return (['Admin'].includes(this.$store.getters.userInfo.roletype) ||
|
||||
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account)) &&
|
||||
this.resource.isready && this.resource.templatetype !== 'SYSTEM'
|
||||
return (['Admin'].includes(this.$store.getters.userInfo.roletype) || // If admin or owner or belongs to current project
|
||||
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account) ||
|
||||
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.projectid && this.$store.getters.project && this.$store.getters.project.id && this.resource.projectid === this.$store.getters.project.id)) &&
|
||||
(this.resource.isready || !this.resource.status || this.resource.status.indexOf('Downloaded') === -1) && // Template is ready or downloaded
|
||||
this.resource.templatetype !== 'SYSTEM'
|
||||
},
|
||||
deleteTemplate () {
|
||||
const params = {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
import { api } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'ZoneResources',
|
||||
name: 'Resources',
|
||||
props: {
|
||||
resource: {
|
||||
type: Object,
|
||||
|
|
@ -66,10 +66,11 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
fetchData () {
|
||||
const entity = this.$route.meta.name + 'id'
|
||||
const params = {}
|
||||
params[entity] = this.resource.id
|
||||
this.fetchLoading = true
|
||||
api('listCapacity', {
|
||||
zoneid: this.resource.id
|
||||
}).then(response => {
|
||||
api('listCapacity', params).then(response => {
|
||||
this.resourcesList = response.listcapacityresponse.capacity
|
||||
this.animatePercentVals()
|
||||
}).catch(error => {
|
||||
|
|
@ -111,7 +111,11 @@ export default {
|
|||
isSystem: true,
|
||||
zoneId: this.resource.zoneid
|
||||
}).then(json => {
|
||||
this.publicNetwork = json.listnetworksresponse.network[0] || {}
|
||||
if (json.listnetworksresponse && json.listnetworksresponse.network && json.listnetworksresponse.network.length > 0) {
|
||||
this.publicNetwork = json.listnetworksresponse.network[0]
|
||||
} else {
|
||||
this.publicNetwork = {}
|
||||
}
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
}).finally(() => {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
banner
|
||||
:message="$t('message.action.router.health.checks.disabled.warning')" />
|
||||
<div v-else>
|
||||
<a-button :disabled="!('getRouterHealthCheckResults' in $store.getters.apis)" type="primary" icon="download" style="width: 100%; margin-bottom: 15px" @click="showGetHelathCheck">
|
||||
<a-button :disabled="!('getRouterHealthCheckResults' in $store.getters.apis)" type="primary" icon="play-circle" style="width: 100%; margin-bottom: 15px" @click="showGetHelathCheck">
|
||||
{{ $t('label.action.router.health.checks') }}
|
||||
</a-button>
|
||||
<a-table
|
||||
|
|
|
|||
|
|
@ -62,13 +62,16 @@
|
|||
<div class="form__label">{{ $t('label.cidr') }}</div>
|
||||
<a-input v-model="newRule.cidrlist"></a-input>
|
||||
</div>
|
||||
<div class="form__item" v-if="addType === 'account'">
|
||||
<div class="form__label">{{ $t('label.account.and.security.group') }}</div>
|
||||
<div style="display:flex;">
|
||||
<template v-if="addType === 'account'">
|
||||
<div class="form__item">
|
||||
<div class="form__label">{{ $t('label.account') }}</div>
|
||||
<a-input v-model="newRule.usersecuritygrouplist.account" style="margin-right: 10px;"></a-input>
|
||||
</div>
|
||||
<div class="form__item">
|
||||
<div class="form__label">{{ $t('label.securitygroup') }}</div>
|
||||
<a-input v-model="newRule.usersecuritygrouplist.group"></a-input>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="form__item" style="flex: 0">
|
||||
<a-button :disabled="!('authorizeSecurityGroupInress' in $store.getters.apis) && !('authorizeSecurityGroupEgress' in $store.getters.apis)" type="primary" @click="handleAddRule">{{ $t('label.add') }}</a-button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,9 @@
|
|||
</span>
|
||||
<a-select
|
||||
allowClear
|
||||
v-decorator="['externalid'] "
|
||||
v-decorator="['externalid', {
|
||||
rules: [{ required: true, message: `${this.$t('message.error.select')}` }]
|
||||
}] "
|
||||
:loading="externals.loading">
|
||||
<a-select-option v-for="opt in externals.opts" :key="opt.id">
|
||||
{{ opt.name }}
|
||||
|
|
|
|||
Loading…
Reference in New Issue