diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index d3127f9f..c98a0608 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -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; diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 89913941..dd5fe1e5 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -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 {