committed by
Julien Fontanet
parent
fad6830863
commit
1257f01027
@@ -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>
|
||||
: []
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -74,3 +74,7 @@
|
||||
.fixedWidth {
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
.tags {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
{_('newVmBootAfterCreate')}
|
||||
</Item>
|
||||
<Item className={styles.tags}>
|
||||
<Tags labels={tags} onChange={this._linkState('tags')} />
|
||||
</Item>
|
||||
</SectionContent>,
|
||||
<SectionContent>
|
||||
<Item label='newVmCpuWeightLabel'>
|
||||
|
||||
Reference in New Issue
Block a user