compute: VM deployment form group template/iso (#470)

Fixes #468

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Hoang Nguyen 2020-07-01 15:43:20 +07:00 committed by Rohit Yadav
parent 360bc5f050
commit 7e7dbaf65c
2 changed files with 90 additions and 176 deletions

View File

@ -33,26 +33,10 @@
class="radio-group__radio"
:value="os.id">
{{ os.displaytext }}&nbsp;
<a-tag
:visible="os.ispublic && !os.isfeatured"
color="blue"
@click="onFilterTag('is: public')"
>{{ $t('label.ispublic') }}</a-tag>
<a-tag
:visible="os.isfeatured"
color="green"
@click="onFilterTag('is: featured')"
>{{ $t('label.isfeatured') }}</a-tag>
<a-tag
:visible="isSelf(os)"
color="orange"
@click="onFilterTag('is: self')"
>{{ $t('label.isself') }}</a-tag>
<a-tag
:visible="isShared(os)"
color="cyan"
@click="onFilterTag('is: shared')"
>{{ $t('label.isshared') }}</a-tag>
<os-logo
class="radio-group__os-logo"
:osId="os.ostypeid"
:os-name="os.osName" />
</a-radio>
</a-radio-group>
</a-list-item>
@ -74,10 +58,11 @@
</template>
<script>
import store from '@/store'
import OsLogo from '@/components/widgets/OsLogo'
export default {
name: 'TemplateIsoRadioGroup',
components: { OsLogo },
props: {
osList: {
type: Array,
@ -95,10 +80,6 @@ export default {
type: Number,
default: 0
},
osType: {
type: String,
default: ''
},
preFillContent: {
type: Object,
default: () => {}
@ -112,20 +93,23 @@ export default {
}
},
mounted () {
if (this.inputDecorator === 'templateid') {
this.value = !this.preFillContent.templateid ? this.selected : this.preFillContent.templateid
} else {
this.value = !this.preFillContent.isoid ? this.selected : this.preFillContent.isoid
this.onSelectTemplateIso()
},
watch: {
selected (newVal, oldVal) {
if (newVal === oldVal) return
this.onSelectTemplateIso()
}
this.$emit('emit-update-template-iso', this.inputDecorator, this.value)
},
methods: {
isShared (item) {
return !item.ispublic && (item.account !== store.getters.userInfo.account)
},
isSelf (item) {
return !item.ispublic && (item.account === store.getters.userInfo.account)
onSelectTemplateIso () {
if (this.inputDecorator === 'templateid') {
this.value = !this.preFillContent.templateid ? this.selected : this.preFillContent.templateid
} else {
this.value = !this.preFillContent.isoid ? this.selected : this.preFillContent.isoid
}
this.$emit('emit-update-template-iso', this.inputDecorator, this.value)
},
updateSelectionTemplateIso (id) {
this.$emit('emit-update-template-iso', this.inputDecorator, id)
@ -139,9 +123,6 @@ export default {
this.page = page
this.pageSize = pageSize
this.$forceUpdate()
},
onFilterTag (tag) {
this.$emit('handle-filter-tag', tag)
}
}
}
@ -151,13 +132,25 @@ export default {
.radio-group {
display: block;
/deep/.ant-radio {
width: 35px;
}
&__radio {
margin: 0.5rem 0;
}
}
.ant-tag {
margin-left: 0.4rem;
/deep/span:last-child {
display: inline-block;
}
}
&__os-logo {
position: absolute;
top: 0;
left: 0;
margin-top: 2px;
margin-left: 23px;
}
}
/deep/.ant-spin-container {

View File

@ -17,74 +17,29 @@
<template>
<div>
<span class="filter-group">
<a-input-search
class="search-input"
:placeholder="$t('label.search')"
v-model="filter"
@search="filterDataSource">
<a-popover
placement="bottomRight"
slot="addonAfter"
trigger="click"
v-model="visibleFilter">
<template slot="content">
<a-form
style="width: 170px"
:form="form"
layout="vertical"
@submit="handleSubmit">
<a-form-item :label="$t('label.filter')">
<a-select
allowClear
mode="multiple"
v-decorator="['filter']">
<a-select-option
v-for="(opt) in filterOpts"
:key="opt.id">{{ $t('label.' + opt.name) }}</a-select-option>
</a-select>
</a-form-item>
<div class="filter-group-button">
<a-button
class="filter-group-button-clear"
type="default"
size="small"
icon="stop"
@click="onClear">Clear</a-button>
<a-button
class="filter-group-button-search"
type="primary"
size="small"
icon="search"
@click="handleSubmit">Search</a-button>
</div>
</a-form>
</template>
<a-button
class="filter-group-button"
icon="filter"
size="small"/>
</a-popover>
</a-input-search>
</span>
<a-input-search
class="search-input"
:placeholder="$t('label.search')"
v-model="filter"
@search="filterDataSource">
</a-input-search>
<a-spin :spinning="loading">
<a-tabs
:animated="false"
:defaultActiveKey="Object.keys(dataSource)[0]"
v-model="filterType"
tabPosition="top"
v-model="osType"
@change="changeOsName">
<a-tab-pane v-for="(osList, osName) in dataSource" :key="osName">
<span slot="tab">
<os-logo :os-name="osName"></os-logo>
</span>
@change="changeFilterType">
<a-tab-pane
v-for="filterItem in filterOpts"
:key="filterItem.id"
:tab="$t(filterItem.name)">
<TemplateIsoRadioGroup
v-if="osType===osName"
:osType="osType"
:osList="dataSource[osName]"
v-if="filterType===filterItem.id"
:osList="dataSource[filterItem.id]"
:itemCount="itemCount[filterItem.id]"
:input-decorator="inputDecorator"
:selected="checkedValue"
:itemCount="itemCount[osName]"
:preFillContent="preFillContent"
@handle-filter-tag="filterDataSource"
@emit-update-template-iso="updateTemplateIso"
@ -96,15 +51,13 @@
</template>
<script>
import OsLogo from '@/components/widgets/OsLogo'
import { getNormalizedOsName } from '@/utils/icons'
import _ from 'lodash'
import TemplateIsoRadioGroup from '@views/compute/wizard/TemplateIsoRadioGroup'
import store from '@/store'
export default {
name: 'TemplateIsoSelection',
components: { TemplateIsoRadioGroup, OsLogo },
components: { TemplateIsoRadioGroup },
props: {
items: {
type: Array,
@ -137,18 +90,20 @@ export default {
visibleFilter: false,
filterOpts: [{
id: 'featured',
name: 'featured'
name: 'label.featured'
}, {
id: 'community',
name: 'community'
name: 'label.community'
}, {
id: 'selfexecutable',
name: 'selfexecutable'
name: 'label.my.templates'
}, {
id: 'sharedexecutable',
name: 'sharedexecutable'
name: 'label.sharedexecutable'
}],
osType: ''
osType: '',
filterType: '',
oldInputDecorator: ''
}
},
watch: {
@ -160,10 +115,11 @@ export default {
this.checkedValue = items[0].id
}
this.dataSource = this.mappingDataSource()
this.osType = Object.keys(this.dataSource)[0]
this.filterType = Object.keys(this.dataSource)[0]
},
inputDecorator (newValue, oldValue) {
if (newValue !== oldValue) {
this.oldInputDecorator = this.inputDecorator
this.filter = ''
}
}
@ -173,25 +129,37 @@ export default {
},
methods: {
mappingDataSource () {
let mappedItems = {}
const itemCount = {}
const mappedItems = {
featured: [],
community: [],
selfexecutable: [],
sharedexecutable: []
}
const itemCount = {
featured: 0,
community: 0,
selfexecutable: 0,
sharedexecutable: 0
}
this.filteredItems.forEach((os) => {
const osName = getNormalizedOsName(os.ostypename)
if (Array.isArray(mappedItems[osName])) {
mappedItems[osName].push(os)
itemCount[osName] = itemCount[osName] + 1
os.osName = getNormalizedOsName(os.ostypename)
if (os.isPublic && os.isfeatured) {
mappedItems.community.push(os)
itemCount.community = itemCount.community + 1
} else if (os.isfeatured) {
mappedItems.featured.push(os)
itemCount.featured = itemCount.featured + 1
} else {
mappedItems[osName] = [os]
itemCount[osName] = 1
const isSelf = !os.ispublic && (os.account === store.getters.userInfo.account)
if (isSelf) {
mappedItems.selfexecutable.push(os)
itemCount.selfexecutable = itemCount.selfexecutable + 1
} else {
mappedItems.sharedexecutable.push(os)
itemCount.sharedexecutable = itemCount.sharedexecutable + 1
}
}
})
mappedItems = _.mapValues(mappedItems, (list) => {
let featuredItems = list.filter((item) => item.isfeatured)
let nonFeaturedItems = list.filter((item) => !item.isfeatured)
featuredItems = _.sortBy(featuredItems, (item) => item.displaytext.toLowerCase())
nonFeaturedItems = _.sortBy(nonFeaturedItems, (item) => item.displaytext.toLowerCase())
return featuredItems.concat(nonFeaturedItems) // pin featured isos/templates at the top
})
this.itemCount = itemCount
return mappedItems
},
@ -262,8 +230,8 @@ export default {
this.filter = ''
this.filterDataSource('')
},
changeOsName (value) {
this.osType = value
changeFilterType (value) {
this.filterType = value
}
}
}
@ -288,51 +256,4 @@ export default {
/deep/.ant-tabs-nav-scroll {
min-height: 45px;
}
.filter-group {
/deep/.ant-input-affix-wrapper {
float: right;
width: calc(100% - 32px);
.ant-input {
border-radius: 4px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
/deep/.ant-input-group-addon {
float: left;
width: 32px;
height: 32px;
border-radius: 4px;
border-right: 0;
border-left: 1px solid #d9d9d9;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
padding: 0 0 0 1px;
}
&-button {
background: inherit;
border: 0;
padding: 0;
}
&-button {
position: relative;
display: block;
min-height: 30px;
&-clear {
position: absolute;
left: 0;
}
&-search {
position: absolute;
right: 0;
}
}
}
</style>