feat(new-vm): create tags during VM creation (#1501)

See #1431
This commit is contained in:
Pierre Donias
2016-09-13 14:17:04 +02:00
committed by Julien Fontanet
parent fad6830863
commit 1257f01027
4 changed files with 95 additions and 51 deletions

View File

@@ -1,12 +1,38 @@
import React from 'react'
import filter from 'lodash/filter'
import includes from 'lodash/includes'
import map from 'lodash/map'
import React from 'react'
import Component from './base-component'
import Icon from './icon'
import propTypes from './prop-types'
const INPUT_STYLE = {
margin: '2px',
maxWidth: '4em'
}
const TAG_STYLE = {
backgroundColor: '#2598d9',
borderRadius: '0.5em',
color: 'white',
fontSize: '0.6em',
margin: '0.2em',
marginTop: '-0.1em',
padding: '0.3em',
verticalAlign: 'middle'
}
const ADD_TAG_STYLE = {
cursor: 'pointer',
fontSize: '0.8em',
marginLeft: '0.2em'
}
const REMOVE_TAG_STYLE = {
cursor: 'pointer'
}
@propTypes({
labels: propTypes.arrayOf(React.PropTypes.string).isRequired,
onChange: propTypes.func,
onDelete: propTypes.func,
onAdd: propTypes.func
})
@@ -22,45 +48,70 @@ export default class Tags extends Component {
this.setState({ editing: false })
}
_addTag = newTag => {
const { labels, onAdd, onChange } = this.props
if (!includes(labels, newTag)) {
onAdd && onAdd(newTag)
onChange && onChange([ ...labels, newTag ])
}
}
_deleteTag = tag => {
const { onChange, onDelete } = this.props
onDelete && onDelete(tag)
onChange && onChange(filter(this.props.labels, t => t !== tag))
}
_onKeyDown = event => {
const { keyCode, target } = event
if (keyCode === 13) {
if (target.value) {
this._addTag(target.value)
target.value = ''
}
} else if (keyCode === 27) {
this._stopEdit()
} else {
return
}
event.preventDefault()
}
render () {
const {
labels,
onDelete,
onAdd
onAdd,
onChange,
onDelete
} = this.props
const deleteTag = (onDelete || onChange) && this._deleteTag
return (
<span className='form-group' style={{ color: '#999' }}>
<Icon icon='tags' />
{' '}
<span>
{map(labels.sort(), (label, index) =>
<Tag label={label} onDelete={onDelete} key={index} />
<Tag label={label} onDelete={deleteTag} key={index} />
)}
</span>
{onAdd
? !this.state.editing
? <span className='add-tag-action' onClick={this._startEdit} style={{cursor: 'pointer'}}>
<Icon icon='add-tag' />
</span>
: <span>
<input
type='text'
autoFocus
style={{maxWidth: '4em', margin: '2px'}}
onKeyDown={event => {
const { target } = event
if (event.keyCode === 13 && target.value) {
onAdd(target.value)
target.value = ''
} else if (event.keyCode === 27) {
this._stopEdit()
}
}}
onBlur={this._stopEdit}
/>
</span>
: []
{(onAdd || onChange) && !this.state.editing
? <span onClick={this._startEdit} style={ADD_TAG_STYLE}>
<Icon icon='add-tag' />
</span>
: <span>
<input
type='text'
autoFocus
style={INPUT_STYLE}
onKeyDown={this._onKeyDown}
onBlur={this._stopEdit}
/>
</span>
}
</span>
)
@@ -68,10 +119,10 @@ export default class Tags extends Component {
}
export const Tag = ({ label, onDelete }) => (
<span className='xo-tag'>
<span style={TAG_STYLE}>
{label}{' '}
{onDelete
? <span onClick={onDelete && (() => onDelete(label))} style={{cursor: 'pointer'}}>
? <span onClick={onDelete && (() => onDelete(label))} style={REMOVE_TAG_STYLE}>
<Icon icon='remove-tag' />
</span>
: []

View File

@@ -138,24 +138,6 @@ $select-input-height: 40px; // Bootstrap input height
text-align: center;
}
// TAG STYLE ===================================================================
.xo-tag {
vertical-align: middle;
background-color: #2598d9;
border-radius: 0.5em;
color: white;
padding: 0.3em;
margin: 0.2em;
margin-top: -0.1em;
font-size: 0.6em;
}
.add-tag-action {
font-size: 0.8em;
margin-left: 0.2em;
}
// GENERAL STYLES ==============================================================
.tag-ip {

View File

@@ -74,3 +74,7 @@
.fixedWidth {
width: 20em;
}
.tags {
font-size: 1.5em;
}

View File

@@ -22,6 +22,7 @@ import React from 'react'
import size from 'lodash/size'
import slice from 'lodash/slice'
import store from 'store'
import Tags from 'tags'
import Tooltip from 'tooltip'
import Wizard, { Section } from 'wizard'
import { Button } from 'react-bootstrap-4/lib'
@@ -211,7 +212,8 @@ export default class NewVm extends BaseComponent {
nbVms: NB_VMS_MIN,
VDIs: [],
VIFs: [],
seqStart: 1
seqStart: 1,
tags: []
})
}
@@ -297,7 +299,8 @@ export default class NewVm extends BaseComponent {
// Boolean: if true, boot the VM right after its creation
bootAfterCreate: state.bootAfterCreate,
cloudConfig,
coreOs: state.template.name_label === 'CoreOS'
coreOs: state.template.name_label === 'CoreOS',
tags: state.tags
}
return state.multipleVms ? createVms(data, state.nameLabels) : createVm(data)
@@ -1195,7 +1198,8 @@ export default class NewVm extends BaseComponent {
namePattern,
nbVms,
seqStart,
showAdvanced
showAdvanced,
tags
} = this.state.state
const { formatMessage } = this.props.intl
return <Section icon='new-vm-advanced' title='newVmAdvancedPanel' done>
@@ -1216,6 +1220,9 @@ export default class NewVm extends BaseComponent {
&nbsp;
{_('newVmBootAfterCreate')}
</Item>
<Item className={styles.tags}>
<Tags labels={tags} onChange={this._linkState('tags')} />
</Item>
</SectionContent>,
<SectionContent>
<Item label='newVmCpuWeightLabel'>