Compare commits

...

7 Commits

Author SHA1 Message Date
Egor Savkin dceac25866 Fix #72 - make side-panel button depend on screen size, same as the appearance
Signed-off-by: Egor Savkin <es@m-labs.hk>
2023-07-26 11:53:27 +08:00
Egor Savkin 1dd336385f Fix shop import json buttons spacing
Signed-off-by: Egor Savkin <es@m-labs.hk>
2023-07-26 11:17:26 +08:00
Egor Savkin 0dbd80142d Remove weird animations from backlog
Signed-off-by: Egor Savkin <es@m-labs.hk>
2023-07-21 17:56:27 +08:00
Egor Savkin 49e97c6972 Fix unused css class
Signed-off-by: Egor Savkin <es@m-labs.hk>
2023-07-21 17:24:31 +08:00
Egor Savkin c7527fbcf0 Fix react-beautiful-dnd warning in development
Signed-off-by: Egor Savkin <es@m-labs.hk>
2023-07-18 10:35:11 +08:00
Egor Savkin 5eaeecbf5b Fix React warnings in development
Signed-off-by: Egor Savkin <es@m-labs.hk>
2023-07-14 15:21:46 +08:00
Egor Savkin 1fa27e5166 A bit more forgotten pr/pl -> pe/ps
Signed-off-by: Egor Savkin <es@m-labs.hk>
2023-07-14 10:42:33 +08:00
8 changed files with 84 additions and 89 deletions

View File

@ -4,7 +4,7 @@
padding: 1em 1em 0; padding: 1em 1em 0;
} }
.simu-clone { .simclone {
z-index: 10; z-index: 10;
} }

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
import React from "react"; import React from "react";
import axios from "axios"; import axios from "axios";
import ReactDOM from "react-dom"; import { createRoot } from "react-dom/client";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
@ -10,12 +10,18 @@ import { v4 as uuidv4 } from 'uuid';
const data = window.shop_data; const data = window.shop_data;
const productStyle = (style, snapshot, removeAnim, hovered, selected) => { const productStyle = (style, snapshot, removeAnim, hovered, selected, cart=false) => {
const custom = { const custom = {
opacity: snapshot.isDragging ? .7 : 1, opacity: snapshot.isDragging ? .7 : 1,
backgroundColor: (hovered || selected) ? '#eae7f7' : 'initial', backgroundColor: (hovered || selected) ? '#eae7f7' : 'initial',
}; };
if (!cart && snapshot.draggingOver == null && // hack for backlog
((!snapshot.isDragging) // prevent next elements from animation
|| (snapshot.isDragging && snapshot.isDropAnimating))) { // prevent dragged element from weird animation
style.transform = "none";
}
if (!snapshot.isDropAnimating) { if (!snapshot.isDropAnimating) {
return { ...style, ...custom}; return { ...style, ...custom};
} }
@ -314,10 +320,10 @@ class Layout extends React.PureComponent {
) : null} ) : null}
<div class={`modal fade ${ showRFQFeedback ? 'show': ''}`} style={{'display': showRFQFeedback ? 'block':'none'}} id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div className={`modal fade ${ showRFQFeedback ? 'show': ''}`} style={{'display': showRFQFeedback ? 'block':'none'}} id="exampleModal" tabIndex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document"> <div className="modal-dialog" role="document">
<div class="modal-content"> <div className="modal-content">
<div class="modal-body rfqFeedback"> <div className="modal-body rfqFeedback">
<div className="d-flex w-100"> <div className="d-flex w-100">
@ -344,8 +350,8 @@ class Layout extends React.PureComponent {
{RFQBodyType === 'import' ? ( {RFQBodyType === 'import' ? (
<div className="w-100"> <div className="w-100">
<form className="form w-100"> <form className="w-100">
<div className="form-group"> <div className="mb-3">
<p className="small"> <p className="small">
Input the JSON description below. Should be something like: Input the JSON description below. Should be something like:
<br /> <br />
@ -353,7 +359,7 @@ class Layout extends React.PureComponent {
</p> </p>
</div> </div>
<div className="form-group w-100"> <div className="mb-3 w-100">
<textarea <textarea
onChange={this.handleCustomConfig} onChange={this.handleCustomConfig}
value={this.state.customconf} value={this.state.customconf}
@ -362,15 +368,15 @@ class Layout extends React.PureComponent {
placeholder="Input JSON description here." /> placeholder="Input JSON description here." />
</div> </div>
{this.state.error ? ( {this.state.error ? (
<div className="form-group"> <div className="mb-3">
<p className="text-danger">{this.state.error}</p> <p className="text-danger">{this.state.error}</p>
</div> </div>
) : null} ) : null}
</form> </form>
<div className="d-flex flex-column flex-sm-row justify-content-end"> <div className="d-flex flex-column flex-sm-row justify-content-end">
<a type="button" onClick={onClickCloseRFQFeedback} class="btn btn-sm btn-outline-primary m-0 mb-2 mb-sm-0 me-sm-2">Close</a> <a type="button" onClick={onClickCloseRFQFeedback} className="btn btn-sm btn-outline-primary m-0 mb-2 mb-sm-0 me-sm-2">Close</a>
<a type="button" onClick={this.handleClickLoad} class={`btn btn-sm btn-primary m-0 ms-sm-2 ${this.state.error ? 'disabled':''}`}>Load configuration</a> <a type="button" onClick={this.handleClickLoad} className={`btn btn-sm btn-primary m-0 ms-sm-2 ${this.state.error ? 'disabled':''}`}>Load configuration</a>
</div> </div>
</div> </div>
) : null} ) : null}
@ -406,6 +412,7 @@ class ProductItem extends React.PureComponent {
static get propTypes() { static get propTypes() {
return { return {
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,
index: PropTypes.number.isRequired,
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
name_codename: PropTypes.string, name_codename: PropTypes.string,
price: PropTypes.number.isRequired, price: PropTypes.number.isRequired,
@ -433,6 +440,7 @@ class ProductItem extends React.PureComponent {
render() { render() {
const { const {
id, id,
index,
name, name,
name_codename, name_codename,
price, price,
@ -453,7 +461,7 @@ class ProductItem extends React.PureComponent {
const render_datasheet_link = (datasheet_file && datasheet_name && ( const render_datasheet_link = (datasheet_file && datasheet_name && (
<div className="ds"> <div className="ds">
<span class='doc-icon'></span> <span className='doc-icon'></span>
<a href={datasheet_file} target="_blank" rel="noopener noreferrer"> <a href={datasheet_file} target="_blank" rel="noopener noreferrer">
{datasheet_name} {datasheet_name}
</a> </a>
@ -464,7 +472,7 @@ class ProductItem extends React.PureComponent {
<section className="productItem"> <section className="productItem">
<div className="content"> <div className="content">
<h3 style={{ 'margin-bottom': name_codename ? '5px' : '20px'}}>{name}</h3> <h3 style={{ 'marginBottom': name_codename ? '5px' : '20px'}}>{name}</h3>
{name_codename ? ( {name_codename ? (
<p>{name_codename}</p> <p>{name_codename}</p>
) : null } ) : null }
@ -482,7 +490,7 @@ class ProductItem extends React.PureComponent {
<img src="/images/shop/icon-add.svg" alt="add" /> <img src="/images/shop/icon-add.svg" alt="add" />
</button> </button>
<Draggable draggableId={id}> <Draggable draggableId={id} index={index}>
{(provided, snapshot) => ( {(provided, snapshot) => (
<React.Fragment> <React.Fragment>
<img <img
@ -678,6 +686,7 @@ class ProductCartItem extends React.PureComponent {
true, true,
hovered ? true : false, hovered ? true : false,
model.selected ? true : false, model.selected ? true : false,
true
)}} )}}
onMouseEnter={this.handleOnMouseEnterRemoveItem.bind(this, index)} onMouseEnter={this.handleOnMouseEnterRemoveItem.bind(this, index)}
onMouseLeave={this.handleOnMouseLeaveRemoveItem.bind(this, index)} onMouseLeave={this.handleOnMouseLeaveRemoveItem.bind(this, index)}
@ -1025,11 +1034,10 @@ class OrderPanel extends React.PureComponent {
</div> </div>
<div> <div>
<input <button
className="btn btn-sm btn-outline-primary m-0 mb-2" className="btn btn-sm btn-outline-primary m-0 mb-2"
style={{'cursor': 'pointer'}} style={{'cursor': 'pointer'}}
value="Import JSON" onClick={onClickOpenImport}>Import JSON</button>
onClick={onClickOpenImport} />
</div> </div>
{isMobile ? ( {isMobile ? (
@ -1255,13 +1263,12 @@ class OrderForm extends React.PureComponent {
placeholder="Additional notes" /> placeholder="Additional notes" />
<div className="d-flex flex-column flex-sm-row justify-content-between"> <div className="d-flex flex-column flex-sm-row justify-content-between">
<input <button
className="btn btn-outline-primary w-100 m-0 mb-2 mb-sm-0 me-sm-2" className="btn btn-outline-primary w-100 m-0 mb-2 mb-sm-0 me-sm-2"
style={{'cursor': 'pointer', 'fontWeight': '700'}} style={{'cursor': 'pointer', 'fontWeight': '700'}}
value="Show JSON" onClick={onClickShow}>Show JSON</button>
onClick={onClickShow} />
<input className="btn btn-primary w-100 m-0 ms-sm-2" type="submit" value={`${isProcessing ? 'Processing ...' : 'Request quote'}`} /> <button className="btn btn-primary w-100 m-0 ms-sm-2" type="submit">{`${isProcessing ? 'Processing ...' : 'Request quote'}`}</button>
</div> </div>
{/*This will open an email window. Send the email to make your request.*/} {/*This will open an email window. Send the email to make your request.*/}
</form> </form>
@ -1512,9 +1519,10 @@ class Backlog extends React.PureComponent {
const ordered_groups = data.categories.map(groupItem => ({ name: groupItem.name, const ordered_groups = data.categories.map(groupItem => ({ name: groupItem.name,
items: groupItem.itemIds.map(itemId => items[itemId]) items: groupItem.itemIds.map(itemId => items[itemId])
})); }));
const groups = ordered_groups.map((group, g_index) => { let item_index = -1;
const groups = ordered_groups.map((group, g_index) => {
return ( return (
<div className="accordion-item"> <div className="accordion-item" key={`${group.name}`}>
<h2 className="accordion-header"> <h2 className="accordion-header">
<button className="accordion-button collapsed" type="button" data-bs-toggle="collapse" <button className="accordion-button collapsed" type="button" data-bs-toggle="collapse"
data-bs-target={`#collapse${g_index}`} aria-expanded="true" aria-controls={`collapse${g_index}`}> data-bs-target={`#collapse${g_index}`} aria-expanded="true" aria-controls={`collapse${g_index}`}>
@ -1524,21 +1532,24 @@ class Backlog extends React.PureComponent {
<div id={`collapse${g_index}`} className="accordion-collapse collapse" aria-labelledby="headingOne" <div id={`collapse${g_index}`} className="accordion-collapse collapse" aria-labelledby="headingOne"
data-bs-parent="#accordion_categories"> data-bs-parent="#accordion_categories">
<div className="accordion-body"> <div className="accordion-body">
{group.items.map(item => ( {group.items.map(item => {
<ProductItem item_index++;
key={item.id} return (
id={item.id} <ProductItem
name={`${item.name_number} ${item.name}`} key={item.id}
name_codename={item.name_codename} id={item.id}
price={item.price} index={item_index}
currency={currency} name={`${item.name_number} ${item.name}`}
image={`/images/${item.image}`} name_codename={item.name_codename}
specs={item.specs} price={item.price}
datasheet_file={item.datasheet_file} currency={currency}
datasheet_name={item.datasheet_name} image={`/images/${item.image}`}
onClickAddItem={onClickAddItem} specs={item.specs}
></ProductItem> datasheet_file={item.datasheet_file}
))} datasheet_name={item.datasheet_name}
onClickAddItem={onClickAddItem}
></ProductItem>
)})}
</div> </div>
</div> </div>
</div> </div>
@ -1961,23 +1972,25 @@ class Shop extends React.PureComponent {
switch(source.droppableId) { switch(source.droppableId) {
case 'backlog': case 'backlog':
this.setState({ if (source.droppableId !== destination.droppableId) {
...this.state, this.setState({
newCardJustAdded: newAdded ? true : false, ...this.state,
columns: { newCardJustAdded: newAdded ? true : false,
...this.state.columns, columns: {
[destination.droppableId]: { ...this.state.columns,
...this.state.columns[destination.droppableId], [destination.droppableId]: {
items: copy( ...this.state.columns[destination.droppableId],
this.state.items, items: copy(
this.state.columns[source.droppableId], this.state.items,
this.state.columns[destination.droppableId], this.state.columns[source.droppableId],
draggableId, this.state.columns[destination.droppableId],
destination, draggableId,
), destination,
),
},
}, },
}, });
}); }
break; break;
case destination.droppableId: case destination.droppableId:
@ -2026,7 +2039,7 @@ class Shop extends React.PureComponent {
} = this.state; } = this.state;
const itemsCloned = Array.from(newItems); const itemsCloned = Array.from(newItems);
const itemsData = {}; const itemsData = [];
const rules = {}; const rules = {};
@ -2310,9 +2323,7 @@ class Shop extends React.PureComponent {
...this.state.columns, ...this.state.columns,
cart: { cart: {
...this.state.columns.cart, ...this.state.columns.cart,
itemsData: { itemsData: itemsData,
...itemsData,
},
} }
}, },
rules: { rules: {
@ -2431,8 +2442,4 @@ class Shop extends React.PureComponent {
} }
} }
createRoot(document.querySelector('#root-shop')).render(<Shop data={data} />);
ReactDOM.render(
<Shop data={data} />,
document.querySelector('#root-shop'),
);

View File

@ -921,7 +921,7 @@ const shop_data = {
id: 'cart', id: 'cart',
title: 'Cart', title: 'Cart',
items: [], items: [],
itemsData: {}, itemsData: [],
}, },
}, },

View File

@ -38,7 +38,7 @@
<div class="card-body p-3 p-md-5 card-artiq"> <div class="card-body p-3 p-md-5 card-artiq">
<div class="col-12 col-md-6 pl-0 pr-0"> <div class="col-12 col-md-6 ps-0 pe-0">
<h5 class="card-title">ARTIQ</h5> <h5 class="card-title">ARTIQ</h5>
@ -73,7 +73,7 @@
<div class="card-body p-3 p-md-5 card-jobs"> <div class="card-body p-3 p-md-5 card-jobs">
<div class="col-12 col-md-6 pl-0 pr-0"> <div class="col-12 col-md-6 ps-0 pe-0">
<h5 class="card-title">Jobs</h5> <h5 class="card-title">Jobs</h5>
@ -104,7 +104,7 @@
<div class="card-body p-3 p-md-5 card-gateware"> <div class="card-body p-3 p-md-5 card-gateware">
<div class="col-12 col-md-6 pl-0 pr-0"> <div class="col-12 col-md-6 ps-0 pe-0">
<h5 class="card-title">Gateware and system-on-chip design</h5> <h5 class="card-title">Gateware and system-on-chip design</h5>

View File

@ -26,26 +26,12 @@
<script> <script>
(function () { (function () {
function deviceIsMobile() { function deviceIsMobile() {
// https://coderwall.com/p/i817wa/one-line-function-to-detect-mobile-devices-with-javascript // Do not rely on User-Agent: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
return ( // Be in sync with css/order-hardware.css
(typeof window.orientation !== 'undefined') || return window.innerWidth < 768;
navigator.userAgent.match(/Android/i) || }
navigator.userAgent.match(/webOS/i) ||
navigator.userAgent.match(/iPhone/i) ||
navigator.userAgent.match(/iPad/i) ||
navigator.userAgent.match(/iPod/i) ||
navigator.userAgent.match(/BlackBerry/i) ||
navigator.userAgent.match(/Windows Phone/i) ||
(navigator.userAgent.indexOf('IEMobile') !== -1)
);
};
window.deviceIsMobile = deviceIsMobile; window.deviceIsMobile = deviceIsMobile;
return;
if (deviceIsMobile()) {
alert('The online crate configuration tool is not available for mobile browsers yet. Please use a desktop computer or email us at sales@m-l****.hk to get a quote.');
}
})(); })();
</script> </script>

View File

@ -2,7 +2,7 @@
<img src="{{ get_url(path=src, cachebust=true) }}" width="40px" height="40px"> <img src="{{ get_url(path=src, cachebust=true) }}" width="40px" height="40px">
<p class="pl-3"> <p class="pe-3">
{{ body | markdown | safe }} {{ body | markdown | safe }}
</p> </p>

View File

@ -17,6 +17,8 @@ module.exports = {
} }
] ]
}, },
//devtool: "inline-source-map",
//mode: "development"
devtool: false, devtool: false,
mode: "production" mode: "production"
}; };