feat(issue19/UI): Displays box to load custom conf + verification format

master
sovanna 2020-04-14 17:51:33 +09:00
parent 413703fd96
commit fdded2702b
2 changed files with 173 additions and 2 deletions

View File

@ -155,6 +155,13 @@ button {
padding-bottom: .5rem;
}
.btn-outline-primary,
.btn-outline-primary:hover {
color: $btn-primary-2;
border-color: $btn-primary-2;
background-color: inherit;
}
.control {
display: flex;
font-size: .8rem;

View File

@ -144,6 +144,7 @@ class Layout extends React.PureComponent {
onClickCloseRFQFeedback: PropTypes.func,
RFQBodyType: PropTypes.string,
RFQBodyOrder: PropTypes.string,
onClickLoadCustomConf: PropTypes.func,
};
}
@ -153,6 +154,117 @@ class Layout extends React.PureComponent {
};
}
constructor(props) {
super(props);
this.state = {
customconf: '',
error: null,
};
this.handleCustomConfig = this.handleCustomConfig.bind(this);
this.handleClickLoad = this.handleClickLoad.bind(this);
this.checkValidation = this.checkValidation.bind(this);
}
handleCustomConfig(e) {
const value = e.target.value;
this.checkValidation(value);
}
checkValidation(conf) {
let conf_obj;
if (!conf) {
conf = this.state.customconf;
}
try {
conf_obj = JSON.parse(conf);
} catch (e) {
return this.setState({
...this.state,
customconf: conf,
customconf_ready: null,
error: 'invalid format',
});
}
if (!conf_obj) {
return this.setState({
...this.state,
customconf: conf,
customconf_ready: null,
error: 'invalid format',
});
}
if ((!conf_obj.items || !conf_obj.type) &&
(Object.prototype.toString.call(conf_obj.items) !== '[object Array]' ||
Object.prototype.toString.call(conf_obj.type) !== '[object String]')) {
return this.setState({
...this.state,
customconf: conf,
customconf_ready: null,
error: 'invalid format',
});
}
if (conf_obj.type !== "desktop" && conf_obj.type !== "rack") {
return this.setState({
...this.state,
customconf: conf,
customconf_ready: null,
error: 'invalid format',
});
}
conf_obj.items.map(function (item) {
try {
return JSON.parse(item);
} catch (e) {
return null;
}
});
conf_obj.items = conf_obj.items.filter(function (item) {
return item;
});
if (conf_obj.items.filter(function (item) {
return Object.prototype.toString.call(item) !== '[object Object]' || !item.pn || Object.prototype.toString.call(item.pn) !== '[object String]';
}).length > 0) {
return this.setState({
...this.state,
customconf: conf,
customconf_ready: null,
error: 'invalid format',
});
}
conf_obj.items = conf_obj.items.map(function (item) {
return {
pn: item.pn,
};
});
this.setState({
...this.state,
customconf: conf,
error: null,
customconf_ready: conf_obj,
});
}
handleClickLoad() {
this.checkValidation();
if (this.props.onClickLoadCustomConf) {
this.props.onClickLoadCustomConf(this.state.customconf_ready);
}
}
render() {
const {
aside,
@ -190,7 +302,7 @@ class Layout extends React.PureComponent {
<div class="modal-content">
<div class="modal-body rfqFeedback">
<div className="d-flex">
<div className="d-flex w-100">
{RFQBodyType === 'email' ? (
<div className="d-flex">
@ -212,6 +324,29 @@ class Layout extends React.PureComponent {
</p>
) : null}
{RFQBodyType === 'import' ? (
<div className="w-100">
<form className="form w-100">
<div className="form-group w-100">
<textarea
onChange={this.handleCustomConfig}
value={this.state.customconf}
className="form-control w-100"
rows="5"
placeholder="Add your custom configuration here. e.g " />
</div>
{this.state.error ? (
<div className="form-group">
<p className="text-danger">{this.state.error}</p>
</div>
) : null}
</form>
<a type="button" onClick={this.handleClickLoad} class="btn btn-sm btn-primary">Load configuration</a>
</div>
) : null}
<div>
<button onClick={onClickCloseRFQFeedback}>
<img src="/images/shop/icon-close.svg" alt="close" />
@ -221,6 +356,7 @@ class Layout extends React.PureComponent {
</div>
</div>
</div>
</div>
</div>
@ -808,6 +944,7 @@ class OrderPanel extends React.PureComponent {
form: PropTypes.element,
isMobile: PropTypes.bool,
onClickToggleMobileSideMenu: PropTypes.func,
onClickOpenImport: PropTypes.func,
};
}
@ -820,7 +957,8 @@ class OrderPanel extends React.PureComponent {
summaryPrice,
form,
isMobile,
onClickToggleMobileSideMenu
onClickToggleMobileSideMenu,
onClickOpenImport,
} = this.props;
return (
@ -834,6 +972,14 @@ class OrderPanel extends React.PureComponent {
{crateMode}
</div>
<div>
<input
className="btn btn-sm btn-outline-primary m-0 mb-2"
style={{'cursor': 'pointer'}}
value="Import configurations"
onClick={onClickOpenImport} />
</div>
{isMobile ? (
<div className="mobileBtnDisplaySideMenu">
<button onClick={onClickToggleMobileSideMenu}>
@ -1395,6 +1541,8 @@ class Shop extends React.PureComponent {
this.handleClickToggleMobileSideMenu = this.handleClickToggleMobileSideMenu.bind(this);
this.handleClickCloseRFQFeedback = this.handleClickCloseRFQFeedback.bind(this);
this.handleClickShowOrder = this.handleClickShowOrder.bind(this);
this.handleClickOpenImport = this.handleClickOpenImport.bind(this);
this.handleLoadCustomConf = this.handleLoadCustomConf.bind(this);
this.timer = null;
}
@ -1617,6 +1765,20 @@ class Shop extends React.PureComponent {
});
}
handleClickOpenImport() {
this.setState({
isProcessing: false,
shouldShowRFQFeedback: true,
RFQBodyType: 'import',
});
}
handleLoadCustomConf(customconf) {
if (customconf) {
console.log('custom conf: ', customconf);
}
}
handleClickSubmit(note, email) {
const crate = {
items: [],
@ -2095,6 +2257,7 @@ class Shop extends React.PureComponent {
newCardJustAdded={newCardJustAdded}
onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
onClickCloseRFQFeedback={this.handleClickCloseRFQFeedback}
onClickLoadCustomConf={this.handleLoadCustomConf}
aside={
<Backlog
currency={currency}
@ -2108,6 +2271,7 @@ class Shop extends React.PureComponent {
main={(
<OrderPanel
onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
onClickOpenImport={this.handleClickOpenImport}
isMobile={isMobile}
title="Order hardware"
description="