Skip to content

Commit 5462b38

Browse files
committed
Added option values
1 parent 22b75ce commit 5462b38

11 files changed

Lines changed: 287 additions & 85 deletions

File tree

locales/admin/en.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,5 +255,7 @@
255255
"position": "Position",
256256
"optionName": "Option name",
257257
"optionControl": "Option control",
258-
"optionControlSelect": "Drop-down list"
258+
"optionControlSelect": "Drop-down list",
259+
"optionValues": "Option values",
260+
"newOptionValue": "New value"
259261
}

src/admin/client/modules/products/actions.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,15 @@ export function setVariantOption(productId, variantId, optionId, valueId) {
382382
}
383383
}
384384

385+
export function createOptionValue(productId, optionId, valueName) {
386+
return (dispatch, getState) => {
387+
return api.products.options.values.create(productId, optionId, { name: valueName }).then(({status, json}) => {
388+
dispatch(fetchOptions(productId))
389+
})
390+
.catch(error => {});
391+
}
392+
}
393+
385394
export function createOption(productId, option) {
386395
return (dispatch, getState) => {
387396
return api.products.options.create(productId, option).then(({status, json}) => {
@@ -391,6 +400,15 @@ export function createOption(productId, option) {
391400
}
392401
}
393402

403+
export function updateOptionValue(productId, optionId, valueId, valueName) {
404+
return (dispatch, getState) => {
405+
return api.products.options.values.update(productId, optionId, valueId, { name: valueName }).then(({status, json}) => {
406+
dispatch(fetchOptions(productId))
407+
})
408+
.catch(error => {});
409+
}
410+
}
411+
394412
export function updateOption(productId, optionId, option) {
395413
return (dispatch, getState) => {
396414
return api.products.options.update(productId, optionId, option).then(({status, json}) => {
@@ -400,6 +418,14 @@ export function updateOption(productId, optionId, option) {
400418
}
401419
}
402420

421+
export function deleteOptionValue(productId, optionId, valueId) {
422+
return (dispatch, getState) => {
423+
return api.products.options.values.delete(productId, optionId, valueId).then(({status, json}) => {
424+
dispatch(fetchOptions(productId))
425+
})
426+
.catch(error => {});
427+
}
428+
}
403429

404430
export function deleteOption(productId, optionId) {
405431
return (dispatch, getState) => {

src/admin/client/modules/products/edit/option/components/form.js

Lines changed: 0 additions & 74 deletions
This file was deleted.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from 'react'
2+
import { Link } from 'react-router'
3+
import { Field, reduxForm } from 'redux-form'
4+
import { TextField, SelectField } from 'redux-form-material-ui'
5+
import { CustomToggle } from 'modules/shared/form'
6+
import OptionValues from './values'
7+
8+
import messages from 'lib/text'
9+
import style from './style.css'
10+
11+
import Paper from 'material-ui/Paper';
12+
import FlatButton from 'material-ui/FlatButton';
13+
import RaisedButton from 'material-ui/RaisedButton';
14+
import MenuItem from 'material-ui/MenuItem';
15+
16+
const validate = values => {
17+
const errors = {}
18+
const requiredFields = ['name']
19+
20+
requiredFields.map(field => {
21+
if (values && !values[field]) {
22+
errors[field] = messages.errors_required;
23+
}
24+
})
25+
26+
return errors
27+
}
28+
29+
class ProductOptionForm extends React.Component {
30+
constructor(props) {
31+
super(props);
32+
}
33+
34+
componentDidMount() {
35+
this.props.fetchData();
36+
}
37+
38+
render() {
39+
let {
40+
handleSubmit,
41+
pristine,
42+
submitting,
43+
initialValues,
44+
deleteOption,
45+
optionValues,
46+
createOptionValue,
47+
updateOptionValue,
48+
deleteOptionValue } = this.props;
49+
50+
return (
51+
<div>
52+
<form onSubmit={handleSubmit} style={{ display: 'initial' }}>
53+
<Paper className="paper-box" zDepth={1}>
54+
<div className={style.innerBox}>
55+
<Field name="name" component={TextField} floatingLabelText={messages.optionName} fullWidth={true}/>
56+
<Field name="position" component={TextField} type="number" floatingLabelText={messages.position} fullWidth={true}/>
57+
<div className={style.shortControl}>
58+
<Field component={SelectField} autoWidth={true} fullWidth={true} name="control" floatingLabelText={messages.optionControl}>
59+
<MenuItem value="select" primaryText={messages.optionControlSelect}/>
60+
</Field>
61+
</div>
62+
<div className={style.shortControl}>
63+
<Field name="required" component={CustomToggle} label={messages.settings_fieldRequired}/>
64+
</div>
65+
</div>
66+
<div className="buttons-box">
67+
<RaisedButton label={messages.actions_delete} style={{ float: 'left'}} onClick={deleteOption} />
68+
<RaisedButton type="submit" label={messages.actions_save} primary={true} className={style.button} disabled={pristine || submitting}/>
69+
</div>
70+
</Paper>
71+
</form>
72+
<OptionValues optionValues={optionValues} createOptionValue={createOptionValue} updateOptionValue={updateOptionValue} deleteOptionValue={deleteOptionValue} />
73+
</div>
74+
)
75+
}
76+
}
77+
78+
export default reduxForm({
79+
form: 'ProductOptionForm',
80+
validate,
81+
enableReinitialize: true
82+
})(ProductOptionForm)

src/admin/client/modules/products/edit/option/components/style.css

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,42 @@
1414
max-width: 300px;
1515
margin-bottom: 20px;
1616
}
17+
18+
19+
20+
.grid {}
21+
22+
.gridRow {
23+
display: flex;
24+
flex-flow: row wrap;
25+
width: 100%;
26+
align-items: center;
27+
justify-content: space-around;
28+
align-items: center;
29+
border-top: 1px solid rgb(224, 224, 224);
30+
}
31+
32+
.gridRow:hover {
33+
background-color: rgba(0, 0, 0, 0.03);
34+
}
35+
36+
.gridColInput {
37+
padding-left: 30px;
38+
flex: 8 1;
39+
}
40+
.gridColButton {
41+
padding-right: 30px;
42+
text-align: right;
43+
flex: 1 1;
44+
}
45+
46+
.textInput {
47+
width: 100%;
48+
margin: 0;
49+
padding: 0;
50+
border: none;
51+
outline: none;
52+
background-color: transparent;
53+
font-size: 15px;
54+
height: 60px;
55+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import React from 'react'
2+
import {Link} from 'react-router'
3+
4+
import messages from 'lib/text'
5+
import style from './style.css'
6+
7+
import Paper from 'material-ui/Paper';
8+
import FontIcon from 'material-ui/FontIcon';
9+
import IconButton from 'material-ui/IconButton';
10+
11+
class OptionValueEdit extends React.Component {
12+
constructor(props) {
13+
super(props);
14+
this.state = {
15+
value: props.value.name
16+
}
17+
this.onChange = this.onChange.bind(this);
18+
this.onBlur = this.onBlur.bind(this);
19+
this.onDelete = this.onDelete.bind(this);
20+
}
21+
22+
onChange = (e) => {
23+
this.setState({ value: e.target.value });
24+
}
25+
26+
onBlur = (e) => {
27+
this.props.onChange(this.props.value.id, this.state.value);
28+
}
29+
30+
onDelete = () => {
31+
this.props.onDelete(this.props.value.id);
32+
}
33+
34+
render() {
35+
const { value } = this.state;
36+
37+
return (
38+
<div className={style.gridRow}>
39+
<div className={style.gridColInput}>
40+
<input type="text" className={style.textInput} value={value} onChange={this.onChange} onBlur={this.onBlur} />
41+
</div>
42+
<div className={style.gridColButton}>
43+
<IconButton title={messages.actions_delete} onTouchTap={this.onDelete} tabIndex={-1}>
44+
<FontIcon color="#a1a1a1" className="material-icons">delete</FontIcon>
45+
</IconButton>
46+
</div>
47+
</div>
48+
)
49+
}
50+
}
51+
52+
class OptionValueAdd extends React.Component {
53+
constructor(props) {
54+
super(props);
55+
this.state = {
56+
value: ''
57+
}
58+
this.onChange = this.onChange.bind(this);
59+
this.onCreate = this.onCreate.bind(this);
60+
this.handleKeyPress = this.handleKeyPress.bind(this);
61+
}
62+
63+
onChange = (e) => {
64+
this.setState({ value: e.target.value });
65+
}
66+
67+
onCreate = () => {
68+
this.props.onCreate(this.state.value);
69+
this.setState({ value: '' });
70+
}
71+
72+
handleKeyPress(e) {
73+
if (e.keyCode === 13 || e.which === 13) {
74+
this.onCreate();
75+
}
76+
}
77+
78+
render() {
79+
const { value } = this.state;
80+
81+
return (
82+
<div className={style.gridRow}>
83+
<div className={style.gridColInput}>
84+
<input type="text" className={style.textInput} value={value} placeholder={messages.newOptionValue} onChange={this.onChange} onKeyPress={this.handleKeyPress} />
85+
</div>
86+
<div className={style.gridColButton}>
87+
<IconButton title={messages.actions_add} onTouchTap={this.onCreate} tabIndex={-1}>
88+
<FontIcon color="#a1a1a1" className="material-icons">add_circle</FontIcon>
89+
</IconButton>
90+
</div>
91+
</div>
92+
)
93+
}
94+
}
95+
96+
const OptionValues = ({ optionValues, createOptionValue, updateOptionValue, deleteOptionValue }) => {
97+
const valueRows = optionValues.map((value, index) => (
98+
<OptionValueEdit key={index} value={value} onChange={updateOptionValue} onDelete={deleteOptionValue} />
99+
));
100+
101+
return (
102+
<Paper className="paper-box" zDepth={1}>
103+
<div className="blue-title" style={{ padding: '20px 30px' }}>{messages.optionValues}</div>
104+
<div className={style.grid}>
105+
{valueRows}
106+
<OptionValueAdd onCreate={createOptionValue} />
107+
</div>
108+
</Paper>
109+
)
110+
}
111+
112+
export default OptionValues;

0 commit comments

Comments
 (0)