Compare commits

..

5 Commits

Author SHA1 Message Date
Egor Savkin b53e191528 Update and clean up NPM dependencies
npm audit also reported 0 vulnerabilities

Signed-off-by: Egor Savkin <es@m-labs.hk>
2024-08-05 11:26:28 +08:00
Egor Savkin 52c05c2e2a Move out subcomponents of ProductItem
This improves maintenance as it reduces complexity of the ProductItem component and allows seeing components in react dev tools

Signed-off-by: Egor Savkin <es@m-labs.hk>
2024-08-05 11:25:32 +08:00
Egor Savkin c7b0d5568c Fix options pop up being both first and last
Signed-off-by: Egor Savkin <es@m-labs.hk>
2024-08-05 11:25:32 +08:00
Egor Savkin 68677dce6e Make tooltip icons inline
Signed-off-by: Egor Savkin <es@m-labs.hk>
2024-08-05 10:29:26 +08:00
Egor Savkin b0ef9d07fc Remove unused type field from shop_data
Signed-off-by: Egor Savkin <es@m-labs.hk>
2024-08-05 10:29:01 +08:00
9 changed files with 1061 additions and 1167 deletions

2080
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,31 +14,33 @@
"type": "git",
"url": "https://git.m-labs.hk/M-Labs/web2019.git"
},
"dependencies": {
"@hello-pangea/dnd": "^16.6.0",
"bootstrap": "^5.3.3",
"json-logic-js": "^2.0.5",
"react": "^18.3.1",
"react-bootstrap": "^2.10.4",
"uuid": "^9.0.1",
"zustand": "^4.5.4"
},
"devDependencies": {
"@babel/cli": "^7.23.9",
"@babel/core": "^7.24.0",
"@babel/preset-env": "^7.24.0",
"@babel/preset-react": "^7.23.3",
"@babel/cli": "^7.24.8",
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/preset-react": "^7.24.7",
"@uidotdev/usehooks": "^2.4.1",
"babel-loader": "^9.1.3",
"babel-preset-minify": "^0.5.2",
"bootstrap": "^5.3.3",
"jquery": "^3.7.1",
"react": "^18.2.0",
"react-bootstrap": "^2.10.2",
"@hello-pangea/dnd": "^16.5.0",
"react-dom": "^18.2.0",
"uuid": "^9.0.1",
"webpack": "^5.90.3",
"webpack": "^5.93.0",
"webpack-cli": "^5.1.4",
"json-logic-js": "^2.0.2",
"zustand": "^4.5.2",
"@uidotdev/usehooks":"^2.4.1",
"webpack-preprocessor-loader": "^1.3.0"
},
"babel": {
"presets": [
"@babel/preset-react",
["@babel/preset-env", {
[
"@babel/preset-env",
{
"targets": {
"browsers": [
">0.25%",
@ -46,7 +48,8 @@
"not op_mini all"
]
}
}]
}
]
]
}
}

File diff suppressed because one or more lines are too long

View File

@ -6,9 +6,33 @@ import {useShopStore} from "./shop_store";
// #!render_count
import {useRenderCount} from "@uidotdev/usehooks";
function DatasheetLink({datasheet_file, datasheet_name}) {
return datasheet_file && datasheet_name && (<div className="ds">
<span className='doc-icon'></span>
<a href={datasheet_file} target="_blank" rel="noopener noreferrer">
{datasheet_name}
</a>
</div>)
}
function CardSpecs({specs}) {
return specs && specs.length > 0 && (<ul>
{specs.map((spec, index) =>
<li key={index}>{spec}</li>
)}
</ul>)
}
function AddButton({onAdd}) {
return <button onClick={onAdd}>
<img src="/images/shop/icon-add.svg" alt="add"/>
</button>
}
/**
* Component that renders a product.
* Used in the aside (e.g catalog of product)
* Used in the aside (e.g catalog of products)
*/
export function ProductItem({card_index}) {
// #!render_count
@ -16,33 +40,14 @@ export function ProductItem({card_index}) {
const getCardDescription = useShopStore((state) => state.getCardDescription);
const currency = useShopStore((state) => state.currency);
const onAddCard = useShopStore((state) => state.addCardFromCatalog);
const addCardFromCatalog = useShopStore((state) => state.addCardFromCatalog);
const card = getCardDescription(card_index);
// #!render_count
console.log("ProductItem renders: ", renderCount)
const render_specs = (card.specs && card.specs.length > 0 && (
<ul>
{card.specs.map((spec, index) =>
<li key={index}>{spec}</li>
)}
</ul>
));
const render_datasheet_link = (card.datasheet_file && card.datasheet_name && (
<div className="ds">
<span className='doc-icon'></span>
<a href={card.datasheet_file} target="_blank" rel="noopener noreferrer">
{card.datasheet_name}
</a>
</div>
));
return (
<section className="productItem">
<div className="content">
<h3 style={{'marginBottom': card.name_codename ? '5px' : '20px'}}>{card.name_number} {card.name}</h3>
{card.name_codename ? (
@ -51,16 +56,13 @@ export function ProductItem({card_index}) {
<div className="price">{`${currency} ${formatMoney(card.price)}`}</div>
{render_specs}
<CardSpecs specs={card.specs}/>
{render_datasheet_link}
<DatasheetLink datasheet_file={card.datasheet_file} datasheet_name={card.datasheet_name}/>
</div>
<div className="content">
<button onClick={() => onAddCard(null, card_index, null)}>
<img src="/images/shop/icon-add.svg" alt="add"/>
</button>
<AddButton onAdd={() => addCardFromCatalog(null, card_index, null)} />
<Draggable draggableId={card.id + card_index} index={card_index}>
{(provided, snapshot) => (
@ -83,10 +85,7 @@ export function ProductItem({card_index}) {
</React.Fragment>
)}
</Draggable>
</div>
</section>
);
}

View File

@ -12,7 +12,7 @@ export function DialogPopup({options, data, target, id, big, first, last, option
}
);
let div_classes = `overlayVariant border rounded ${big ? "overlay-bigcard" : "overlay-smallcard"} ${(!big && first) ? "overlay-first" : ""} ${(!big && last) ? "overlay-last" : ""} ${options_class || ""}`;
let div_classes = `overlayVariant border rounded ${big ? "overlay-bigcard" : "overlay-smallcard"} ${(!big && first) ? "overlay-first" : ""} ${(!big && last && !first) ? "overlay-last" : ""} ${options_class || ""}`;
const handleClick = (_event) => {
setShow(!show);
};

View File

@ -39,9 +39,10 @@ class Line extends Component {
<div className="shop-line" key={this.props.id}>
<label htmlFor={key} className="form-label">
{this.props.icon && <img src={`/images${this.props.icon}`} className="options-icon"/>}
{this.props.title}:
</label>
{this.props.title}
{this.props.tip && <Tip id={this.props.id + "tooltip"} tip={this.props.tip}/>}
:
</label>
<input type="text" className={`form-control form-control-sm ${this.state.valid ? "" : "options-invalid"}`} id={key} onChange={this.handleChange}
value={this.state.text}/>
</div>

View File

@ -49,8 +49,8 @@ class Switch extends Component {
<label className="form-check-label" htmlFor={key} style={{"display": "inline"}}>
{this.props.icon && <img src={`/images${this.props.icon}`} className="options-icon"/>}
{this.props.title}
</label>
{this.props.tip && <Tip id={this.props.id + "tooltip"} tip={this.props.tip}/>}
</label>
</div>
</div>
);

View File

@ -65,8 +65,8 @@ class SwitchLine extends Component {
<label className="form-check-label" htmlFor={key + "switch"}>
{this.props.icon && <img src={`/images${this.props.icon}`} className="options-icon"/>}
{this.props.title}
</label>
{this.props.tip && <Tip id={this.props.id + "tooltip"} tip={this.props.tip}/>}
</label>
</div>
<input type="text" className={`form-control form-control-sm ${this.state.valid ? "" : "options-invalid"}`} id={key + "line"} onChange={this.handleText}
value={this.state.text} disabled={!this.state.checked}/>

View File

@ -179,7 +179,6 @@ const shop_data = {
'Price includes bitstream generation, flashing, testing, and firmware updates for 1 year (USD 1,400.00).',
],
size: 'big',
type: 'kasli',
options: [
{type: "Radio", args: {title: "DRTIO role", outvar: "drtio_role", variants: ["standalone", "master", "satellite"], tip: "Distributed Real Time Input/Output allows ARTIQ RTIO channels to be distributed among several satellite devices synchronized and controlled by a central core(master) device. Standalone option disables this feature."}},
{
@ -244,7 +243,6 @@ const shop_data = {
'4 MMCX clock outputs.',
],
size: 'big',
type: 'kasli',
hp: 8,
nbrSlotMin: 0,
nbrSlotMax: 12,
@ -316,7 +314,6 @@ const shop_data = {
'A pair of VHDCI carriers is a simple, low-latency and low-cost alternative to DRTIO for some applications.',
],
size: 'big',
type: 'vhdcicarrier',
resources: [
{name: "eem", max: 8},
],
@ -347,7 +344,6 @@ const shop_data = {
datasheet_file: '/docs/sinara-datasheets/2118-2128.pdf',
datasheet_name: '2118/2128 BNC/SMA-TTL datasheet',
size: 'big',
type: null,
options: [
{
"if": [
@ -457,7 +453,6 @@ const shop_data = {
}
],
size: 'small',
type: null,
warnings: [
"no_eem_source"
],
@ -549,7 +544,6 @@ const shop_data = {
}
],
size: 'small',
type: null,
warnings: [
"no_eem_source"
],
@ -636,7 +630,6 @@ const shop_data = {
}
],
size: 'small',
type: null,
warnings: [
"no_eem_source"
],
@ -700,7 +693,6 @@ const shop_data = {
}
],
size: 'small',
type: 'urukul',
warnings: [
"no_eem_source",
"no_clk_source"
@ -739,7 +731,6 @@ const shop_data = {
fallback: {text: "125 MHz", checked: false}}}
],
size: 'small',
type: 'urukul',
warnings: [
"no_eem_source",
"no_clk_source"
@ -773,7 +764,6 @@ const shop_data = {
{type: "Radio", args: {title: "Variant", outvar: "variant", variants: ["Baseband", "Upconverter"], fallback: 1}},
],
size: 'small',
type: 'urukul',
warnings: [
"no_eem_source",
"no_clk_source"
@ -816,7 +806,6 @@ const shop_data = {
datasheet_file: '/docs/sinara-datasheets/5432.pdf',
datasheet_name: '5432 Zotino datasheet',
size: 'small',
type: 'zotino',
warnings: [
"no_eem_source",
"idc_resource"
@ -846,7 +835,6 @@ const shop_data = {
'Channels can also be broken out to BNC or SMA using IDC-BNC, IDC-SMA or IDC-MCX cards.'
],
size: 'small',
type: 'zotino',
warnings: [
"no_eem_source",
"idc_resource",
@ -872,7 +860,6 @@ const shop_data = {
'Breaking out all 32 channels from a Zotino requires 4 IDC-BNC cards.'
],
size: 'big',
type: 'idc-bnc',
warnings: [
"no_idc_source"
],
@ -931,7 +918,6 @@ const shop_data = {
'Breaking out all 32 channels from a Zotino requires 4 SMA-IDC cards.'
],
size: 'small',
type: 'idc-bnc',
warnings: [
"no_idc_source"
],
@ -951,7 +937,6 @@ const shop_data = {
'Connects an external HD68 cable to IDC-BNC, IDC-SMA or IDC-MCX cards.',
],
size: 'small',
type: 'hd68',
options: [
{type: "Radio", args: {title: "Cable length", outvar: "hd68_cable_len", variants: ["1 M", "2 M", "3 M"], tip: "The desired length of the HD68 cable", fallback: 1}},
],
@ -1008,7 +993,6 @@ const shop_data = {
}
],
size: 'big',
type: 'novo',
warnings: [
"no_eem_source"
],
@ -1035,7 +1019,6 @@ const shop_data = {
{type: "Radio", args: {title: "Connectors", outvar: "n_eem", variants: ["1 EEM", "2 EEM", "3 EEM"], tip: "Number of EEM ports to use.", fallback: 1}},
],
size: 'small',
type: 'koster',
warnings: [
"no_eem_source"
],
@ -1064,7 +1047,6 @@ const shop_data = {
],
options_class: "clocker",
size: 'small',
type: 'clocker',
warnings: [
"no_eem_source",
"no_clk_source",
@ -1105,7 +1087,6 @@ const shop_data = {
],
options_class: "stabilizer",
size: 'small',
type: null,
warnings: [
"no_eem_source"
],
@ -1140,7 +1121,6 @@ const shop_data = {
],
options_class: "stabilizer",
size: 'small',
type: null,
warnings: [
"no_eem_source"
],
@ -1170,7 +1150,6 @@ const shop_data = {
fallback: {text: "125 MHz", checked: false}}}
],
size: 'small',
type: null,
warnings: [
"no_eem_source",
"no_clk_source"
@ -1199,7 +1178,6 @@ const shop_data = {
fallback: {text: "125 MHz", checked: false}}}
],
size: 'big',
type: null,
warnings: [
"no_eem_source",
"no_clk_source"
@ -1229,7 +1207,6 @@ const shop_data = {
{type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}}
],
size: 'small',
type: null,
warnings: [
"no_eem_source"
],
@ -1253,7 +1230,6 @@ const shop_data = {
'Can stabilize temperature of Sinara 5432 DAC or external devices containing TEC and thermistor.'
],
size: 'small',
type: null,
consumes: {
hp: 4
},
@ -1277,7 +1253,6 @@ const shop_data = {
'Included remote analog front-end (AFE) board converts differential signals to ±10V single-ended at the point of use, with additional gain and filtering.',
],
size: 'big',
type: null,
warnings: [
"no_eem_source",
"no_clk_source"
@ -1312,7 +1287,6 @@ const shop_data = {
{type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on ADC channel #1"}}
],
size: 'big',
type: null,
warnings: [
"no_eem_source",
"no_clk_source"
@ -1342,7 +1316,6 @@ const shop_data = {
"Optional - external power brick will be shipped free of charge if removed."
],
size: 'big',
type: null,
warnings: [],
consumes: {
hp: 4,