From d543e5432606e859c78501d01269a9739d3f9edd Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Thu, 17 Aug 2023 14:42:47 +0800 Subject: [PATCH 01/42] Add basic demo example Kinda works, but buggy Signed-off-by: Egor Savkin --- package.json | 19 ++++----- sass/css/_shop.scss | 25 ++++++++++-- static/js/shop.jsx | 58 ++++++++++++++++++++++++++-- static/js/shop_components.jsx | 73 +++++++++++++++++++++++++++++++++++ static/js/shop_data.js | 28 ++++++++++++++ 5 files changed, 188 insertions(+), 15 deletions(-) create mode 100644 static/js/shop_components.jsx diff --git a/package.json b/package.json index a5e86c1..382b8e8 100644 --- a/package.json +++ b/package.json @@ -16,18 +16,19 @@ "@babel/core": "^7.22.8", "@babel/preset-env": "^7.22.7", "@babel/preset-react": "^7.22.5", - "babel-preset-minify": "^0.5.2", + "axios": "^1.4.0", "babel-loader": "^9.1.3", + "babel-preset-minify": "^0.5.2", + "bootstrap": "^5.3.0", + "jquery": "^3.7.0", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", + "react-dom": "^18.2.0", + "uuid": "^9.0.0", "webpack": "^5.88.1", "webpack-cli": "^5.1.4", - "bootstrap": "^5.3.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-beautiful-dnd": "^13.1.1", - "axios": "^1.4.0", - "prop-types": "^15.8.1", - "jquery": "^3.7.0", - "uuid": "^9.0.0", + "json-logic-js": "^2.0.2", "react-bootstrap": "^2.8.0" }, "babel": { diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index edede07..1e04278 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -255,7 +255,7 @@ button { .item-card-name, .price { - > .alert-warning { + > .alert-warning, > .alert-info { background-color: inherit; height: inherit; width: 20px; @@ -382,7 +382,7 @@ button { display: flex; flex-direction: column; /*max-width: 96px;*/ - max-width: 130px; + max-width: 132px; justify-content: flex-start; align-content: center; align-items: center; @@ -432,7 +432,7 @@ button { height: 24px; } - > .alert-warning { + > .alert-warning, > .alert-info { background-color: inherit; height: inherit; width: 20px; @@ -464,6 +464,25 @@ button { } } + .overlayVariant { + top: 0; + width: 100%; + min-height: 70px; + position: absolute; + display: flex; + align-items: center; + justify-content: center; + background-color: white; + color: black; + flex-direction: column; + cursor: pointer; + + p { + font-size: .65rem; + margin: 0; + } + } + } .hovered { diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 77107e1..74b4115 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -6,6 +6,7 @@ import { createRoot } from "react-dom/client"; import PropTypes from "prop-types"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { v4 as uuidv4 } from 'uuid'; +import ProcessOptions from "./shop_components.jsx"; import { OverlayTrigger } from "react-bootstrap"; @@ -593,7 +594,7 @@ class ProductCartItem extends React.PureComponent { index, } = this.props; - let warning; + let warning, options, options_data; if (data && data.warnings) { const warningsKeys = Object.keys(data.warnings); if (warningsKeys && warningsKeys.length > 0) { @@ -602,6 +603,15 @@ class ProductCartItem extends React.PureComponent { } } + + + if (data && data.options) { + console.log(data.options_data); + options = data.options; + if (!data.options_data) data.options_data = {}; + options_data = data.options_data; + } + let render_progress; if (data) { switch(model.type) { @@ -682,6 +692,34 @@ class ProductCartItem extends React.PureComponent { +
+ + {warning ? ( + + ) : (options ? : null) } + + {options ? ( +
+ + {ProcessOptions({options: options, data: options_data, target: options_data})} +
+ ) : null } + + + + {warning && model.showWarning && ( +
+

+ {warning.message} +

+
+ )} +
{model.name_number}
@@ -820,7 +858,9 @@ class Cart extends React.PureComponent { let itemData; if (data.itemsData && index in data.itemsData) { itemData = data.itemsData[index]; + console.log(itemData.options_data); } + return ( - {warning && ( + {warning ? ( + ) : ( + )} {!warning && ( @@ -1771,10 +1817,11 @@ class Shop extends React.PureComponent { type: this.state.currentMode, }; const clonedCart = Array.from(this.state.columns.cart.items); + console.log(clonedCart); for (const i in clonedCart) { const item = clonedCart[i]; crate.items.push({ - 'pn': item.name_number, + 'pn': item.name_number }); } @@ -1985,6 +2032,8 @@ class Shop extends React.PureComponent { const itemsCloned = Array.from(newItems); const itemsData = []; + console.log(prevItems); + console.log(this.state); const rules = {}; @@ -2077,6 +2126,9 @@ class Shop extends React.PureComponent { rules[ddkali.rules.follow.type] = {...ddkali.rules.follow}; } } + console.log(idx); + if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) + itemsData[idx].options_data = this.state.columns.cart.itemsData[idx].options_data; } if (idxK.length === 0) { diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx new file mode 100644 index 0000000..d1fc2bc --- /dev/null +++ b/static/js/shop_components.jsx @@ -0,0 +1,73 @@ +'use strict'; + +import React, {useState} from "react"; +import jsonLogic from 'json-logic-js'; +import { v4 as uuidv4 } from 'uuid'; + +// https://stackoverflow.com/a/70511311 +const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); + +function Radio(target, {title, variants, outvar}) { + console.log(target) + function handleClick(variant) { + console.log(variant) + target[outvar] = variant; + //this.setState() + } + + return ( +
+ {title} + {variants.map((variant, _) => ( +
+ handleClick(variant)} + onChange={() => handleClick(variant)} + /> + +
+ ))} +
+ ); +} + +function MissingComponent(...args) { + console.error("Missing component with args:", args) + return +} + +const componentsList = { + "Radio": Radio, + "Default": MissingComponent, +}; + + +export default function ProcessOptions({options, data, target}) { + let options_t = trueTypeOf(options); + + if (options_t === "array") { + return Array.from( + options.map((option_item, _) => ProcessOptions({options: option_item, data: data, target: target})) + ); + } else if (options_t === "object") { + if ( + trueTypeOf(options.type) === "string" && + trueTypeOf(options.args) === "object" + ) { + if (options.type in componentsList) { + return componentsList[options.type](target, options.args); + }else { + return componentsList["Default"](target, options.args); + } + } else { + return ProcessOptions({options: jsonLogic.apply(options, data), data: data, target: target}); + } + } +} \ No newline at end of file diff --git a/static/js/shop_data.js b/static/js/shop_data.js index cc24cee..0c380af 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -64,6 +64,34 @@ const shop_data = { nbrCurrentClock: 0, slotOccupied: 1, clockOccupied: 0, + options: [ + {type: "Radio", args: {title: "Variant", outvar: "variant", variants: ["standalone", "master", "satellite"]}}, + { + "if": [ + { + "in": [ + {"var": "variant"}, [ + "master", "standalone" + ] + ] + }, + [ + {type: "LineIPv4", args: {title: "IPv4", outvar: "ipv4", default: "192.168.1.75/24"}}, + {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, + {type: "SwitchLine", args: {title: "MAC", outvar: "mac"}}, + {type: "Switch", args: {title: "Ext CLK", outvar: "ext_clk"}}, + ], + null + ] + }, + { + "if": [ + {"===": [{"var": "ext_clk"}, true]}, + {type: "line", args: {title: "Frequency", outvar: "ext_clk"}}, + null + ] + } + ], rules: { maxSlot: { type: 'kasli-max-slot', -- 2.42.0 From 1a7d44c121be422624c23a13c30a89754a9bc2fd Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Thu, 17 Aug 2023 16:41:50 +0800 Subject: [PATCH 02/42] Make it update state Signed-off-by: Egor Savkin --- package-lock.json | 8 +++ static/js/shop.jsx | 12 +++- static/js/shop_components.jsx | 110 ++++++++++++++++++++++------------ 3 files changed, 90 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9ebce87..77875ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,9 @@ "": { "name": "m-labs-zola", "version": "1.0.0", + "dependencies": { + "json-logic-js": "^2.0.2" + }, "devDependencies": { "@babel/cli": "^7.22.6", "@babel/core": "^7.22.8", @@ -3655,6 +3658,11 @@ "node": ">=4" } }, + "node_modules/json-logic-js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/json-logic-js/-/json-logic-js-2.0.2.tgz", + "integrity": "sha512-ZBtBdMJieqQcH7IX/LaBsr5pX+Y5JIW+EhejtM3Ffg2jdN9Iwf+Ht6TbHnvAZ/YtwyuhPaCBlnvzrwVeWdvGDQ==" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 74b4115..44304e2 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -706,7 +706,16 @@ class ProductCartItem extends React.PureComponent { style={{'display': (model.showOverlayRemove && options) ? 'flex' : 'none'}} className="overlayVariant"> - {ProcessOptions({options: options, data: options_data, target: options_data})} + { + options_data[outvar] = value; + this.setState(options_data); + })} + /> ) : null } @@ -867,6 +876,7 @@ class Cart extends React.PureComponent { isTouch={isTouch} hovered={item.id === itemHovered} key={item.id} + id={item.id} index={index} data={itemData} onToggleOverlayRemove={onToggleOverlayRemove} diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index d1fc2bc..79625a6 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -1,60 +1,92 @@ 'use strict'; -import React, {useState} from "react"; +import React, {Component} from "react"; import jsonLogic from 'json-logic-js'; -import { v4 as uuidv4 } from 'uuid'; +import {v4 as uuidv4} from 'uuid'; // https://stackoverflow.com/a/70511311 const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); -function Radio(target, {title, variants, outvar}) { - console.log(target) - function handleClick(variant) { - console.log(variant) - target[outvar] = variant; - //this.setState() +class Radio extends Component { + constructor(props) { + super(props); + // Initialize the state object with the initial values from the props + this.state = { + target: props.target, + outvar: props.outvar, + variants: props.variants, + variant: props.variants[0], + id: props.id + }; + + // Bind the event handler to this + this.handleClick = this.handleClick.bind(this); + this.state.target(this.state.outvar, this.state.variant); } - return ( -
- {title} - {variants.map((variant, _) => ( -
- handleClick(variant)} - onChange={() => handleClick(variant)} - /> - -
- ))} -
- ); + handleClick(variant) { + console.log(variant); + // Update the state object with the new value for outvar + this.setState({ + ...this.state, + variant: variant + }); + this.state.target(this.state.outvar, variant); + } + + render() { + let key = this.state.id + this.state.outvar; + return ( +
+ {this.props.title} + {this.props.variants.map((variant, _) => ( +
+ this.handleClick(variant)} + onChange={() => this.handleClick(variant)} + /> + +
+ ))} +
+ ); + } } -function MissingComponent(...args) { - console.error("Missing component with args:", args) - return +function RadioWrapper(target, id, {title, variants, outvar}) { + return ; +} + + +function MissingComponent(type, id) { + //console.error("Missing component with type:", type) + return
MISSING
} const componentsList = { - "Radio": Radio, + "Radio": RadioWrapper, "Default": MissingComponent, }; -export default function ProcessOptions({options, data, target}) { +export default function ProcessOptions({options, data, target, id}) { let options_t = trueTypeOf(options); if (options_t === "array") { return Array.from( - options.map((option_item, _) => ProcessOptions({options: option_item, data: data, target: target})) + options.map((option_item, i) => ProcessOptions({ + options: option_item, + data: data, + target: target, + id: id + i + })) ); } else if (options_t === "object") { if ( @@ -62,12 +94,12 @@ export default function ProcessOptions({options, data, target}) { trueTypeOf(options.args) === "object" ) { if (options.type in componentsList) { - return componentsList[options.type](target, options.args); - }else { - return componentsList["Default"](target, options.args); + return componentsList[options.type](target, id + options.type, options.args); + } else { + return componentsList["Default"](options.type, id + "missing"); } } else { - return ProcessOptions({options: jsonLogic.apply(options, data), data: data, target: target}); + return ProcessOptions({options: jsonLogic.apply(options, data), data: data, target: target, id: id}); } } } \ No newline at end of file -- 2.42.0 From f93cf142f05f4b96143678b3205618830b6607d4 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Fri, 18 Aug 2023 12:34:30 +0800 Subject: [PATCH 03/42] Fix JSON shop load Signed-off-by: Egor Savkin --- static/js/shop.jsx | 35 +++++++++++++++++++++++------------ static/js/shop_components.jsx | 9 ++++----- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 44304e2..a2c7f46 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -258,6 +258,7 @@ class Layout extends React.PureComponent { conf_obj.items = conf_obj.items.map(function (item) { return { pn: item.pn, + options: item.options ? item.options : null, }; }); @@ -606,7 +607,6 @@ class ProductCartItem extends React.PureComponent { if (data && data.options) { - console.log(data.options_data); options = data.options; if (!data.options_data) data.options_data = {}; options_data = data.options_data; @@ -867,7 +867,6 @@ class Cart extends React.PureComponent { let itemData; if (data.itemsData && index in data.itemsData) { itemData = data.itemsData[index]; - console.log(itemData.options_data); } return ( @@ -1422,7 +1421,7 @@ class OrderSumary extends React.PureComponent { let alert; let warning; - if (itemsData[index]) { + if (itemsData[index] && itemsData[index].warnings) { alert = itemsData[index]; const warningsKeys = Object.keys(alert.warnings); if (warningsKeys && warningsKeys.length > 0) { @@ -1459,7 +1458,7 @@ class OrderSumary extends React.PureComponent { ) : ( )} @@ -1827,11 +1826,14 @@ class Shop extends React.PureComponent { type: this.state.currentMode, }; const clonedCart = Array.from(this.state.columns.cart.items); - console.log(clonedCart); + const clonedCartData = Array.from(this.state.columns.cart.itemsData); + console.log(clonedCartData); for (const i in clonedCart) { const item = clonedCart[i]; + const item_data = clonedCartData[i]; crate.items.push({ - 'pn': item.name_number + 'pn': item.name_number, + 'options': item_data.options_data ? item_data.options_data : null, }); } @@ -1855,9 +1857,11 @@ class Shop extends React.PureComponent { if (!customconf) {return; } const items = this.props.data.items; + console.trace(customconf); const self = this; let new_items = []; + let new_items_data = []; this.setState({ @@ -1878,14 +1882,15 @@ class Shop extends React.PureComponent { ...items[key], }, { id: uuidv4(), + options_data: item.options ? item.options : null, })); + new_items_data.push({options_data: item.options? item.options : null}); } }); return item; }); - this.setState({ ...this.state, columns: { @@ -1893,6 +1898,7 @@ class Shop extends React.PureComponent { cart: { ...this.state.columns.cart, items: new_items, + itemsData: new_items_data, }, }, currentMode: customconf.type, @@ -1906,10 +1912,13 @@ class Shop extends React.PureComponent { type: this.state.currentMode, }; const clonedCart = Array.from(this.state.columns.cart.items); + const clonedCartData = Array.from(this.state.columns.cart.itemsData); for (const i in clonedCart) { const item = clonedCart[i]; + const item_data = clonedCartData[i]; crate.items.push({ 'pn': item.name_number, + 'options': item_data.options_data ? item_data.options_data : null, }); } @@ -2042,8 +2051,6 @@ class Shop extends React.PureComponent { const itemsCloned = Array.from(newItems); const itemsData = []; - console.log(prevItems); - console.log(this.state); const rules = {}; @@ -2136,9 +2143,6 @@ class Shop extends React.PureComponent { rules[ddkali.rules.follow.type] = {...ddkali.rules.follow}; } } - console.log(idx); - if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) - itemsData[idx].options_data = this.state.columns.cart.itemsData[idx].options_data; } if (idxK.length === 0) { @@ -2322,6 +2326,13 @@ class Shop extends React.PureComponent { } } + itemsCloned.forEach((_elem, idx) => { + if (!(idx in itemsData)) itemsData[idx] = {}; + if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) { + itemsData[idx].options_data = this.state.columns.cart.itemsData[idx].options_data; + } + }); + // update state with rules this.setState({ diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 79625a6..3575a38 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -2,7 +2,6 @@ import React, {Component} from "react"; import jsonLogic from 'json-logic-js'; -import {v4 as uuidv4} from 'uuid'; // https://stackoverflow.com/a/70511311 const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); @@ -15,7 +14,7 @@ class Radio extends Component { target: props.target, outvar: props.outvar, variants: props.variants, - variant: props.variants[0], + variant: props.outvar in props.data ? props.data[props.outvar] : props.variants[0], id: props.id }; @@ -60,8 +59,8 @@ class Radio extends Component { } } -function RadioWrapper(target, id, {title, variants, outvar}) { - return ; +function RadioWrapper(target, id, data, {title, variants, outvar}) { + return ; } @@ -94,7 +93,7 @@ export default function ProcessOptions({options, data, target, id}) { trueTypeOf(options.args) === "object" ) { if (options.type in componentsList) { - return componentsList[options.type](target, id + options.type, options.args); + return componentsList[options.type](target, id + options.type, data, options.args); } else { return componentsList["Default"](options.type, id + "missing"); } -- 2.42.0 From ff8a6d54bc38757bea2d041966fc46c92fe917bc Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Fri, 18 Aug 2023 15:51:00 +0800 Subject: [PATCH 04/42] Add switch and line Signed-off-by: Egor Savkin --- static/js/shop.jsx | 2 - static/js/shop_components.jsx | 108 ++++++++++++++++++++++++++++++---- static/js/shop_data.js | 17 +++--- 3 files changed, 104 insertions(+), 23 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index a2c7f46..1b812c0 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -719,8 +719,6 @@ class ProductCartItem extends React.PureComponent { ) : null } - - {warning && model.showWarning && (

diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 3575a38..be43d9f 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -11,32 +11,27 @@ class Radio extends Component { super(props); // Initialize the state object with the initial values from the props this.state = { - target: props.target, - outvar: props.outvar, - variants: props.variants, variant: props.outvar in props.data ? props.data[props.outvar] : props.variants[0], - id: props.id }; // Bind the event handler to this this.handleClick = this.handleClick.bind(this); - this.state.target(this.state.outvar, this.state.variant); + this.props.target(this.props.outvar, this.state.variant); } handleClick(variant) { - console.log(variant); // Update the state object with the new value for outvar this.setState({ ...this.state, variant: variant }); - this.state.target(this.state.outvar, variant); + this.props.target(this.props.outvar, variant); } render() { - let key = this.state.id + this.state.outvar; + let key = this.props.id + this.props.outvar; return ( -

+
{this.props.title} {this.props.variants.map((variant, _) => (
@@ -60,18 +55,105 @@ class Radio extends Component { } function RadioWrapper(target, id, data, {title, variants, outvar}) { - return ; + return ; +} + +class Switch extends Component { + constructor(props) { + super(props); + // Initialize the state object with the initial values from the props + this.state = { + checked: props.outvar in props.data ? props.data[props.outvar] : !!(props.fallback) + }; + + // Bind the event handler to this + this.handleClick = this.handleClick.bind(this); + this.props.target(this.props.outvar, this.state.checked); + } + + handleClick() { + // Update the state object with the new value for outvar + let new_checked = !this.state.checked; + this.setState({ + checked: new_checked + }); + this.props.target(this.props.outvar, new_checked); + } + + render() { + let key = this.props.id + this.props.outvar; + return ( +
+
+ + +
+
+ ); + } +} + +function SwitchWrapper(target, id, data, {title, fallback, outvar}) { + return ; } -function MissingComponent(type, id) { +class Line extends Component { + constructor(props) { + super(props); + // Initialize the state object with the initial values from the props + this.state = { + text: props.outvar in props.data ? props.data[props.outvar] : (props.fallback ? props.fallback : "") + }; + // Bind the event handler to this + this.handleClick = this.handleClick.bind(this); + this.props.target(this.props.outvar, this.state.text); + } + + handleClick(element) { + let text = element.target.value; + this.setState({ + text: text + }); + this.props.target(this.props.outvar, text); + } + + render() { + let key = this.props.id + this.props.outvar; + return ( +
+ + +
+ ); + } +} + +function LineWrapper(target, id, data, {title, fallback, outvar}) { + return ; +} + + +function UnimplementedComponent(type, id) { //console.error("Missing component with type:", type) - return
MISSING
+ return
UNIMPLEMENTED
} const componentsList = { "Radio": RadioWrapper, - "Default": MissingComponent, + "Switch": SwitchWrapper, + "Line": LineWrapper, + "Default": UnimplementedComponent, }; diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 0c380af..6da3d7b 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -76,21 +76,22 @@ const shop_data = { ] }, [ - {type: "LineIPv4", args: {title: "IPv4", outvar: "ipv4", default: "192.168.1.75/24"}}, + {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "MAC", outvar: "mac"}}, {type: "Switch", args: {title: "Ext CLK", outvar: "ext_clk"}}, + { + "if": [ + {"===": [{"var": "ext_clk"}, true]}, + {type: "Line", args: {title: "Frequency", outvar: "ext_clk_freq", fallback: "125 MHz"}}, + null + ] + } ], null ] }, - { - "if": [ - {"===": [{"var": "ext_clk"}, true]}, - {type: "line", args: {title: "Frequency", outvar: "ext_clk"}}, - null - ] - } + null ], rules: { maxSlot: { -- 2.42.0 From ac87fede4b7551d7b401cf1297e08a141c91b221 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Fri, 18 Aug 2023 16:21:56 +0800 Subject: [PATCH 05/42] Add switchline compact design Signed-off-by: Egor Savkin --- static/js/shop.jsx | 1 + static/js/shop_components.jsx | 64 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 1b812c0..ce4c4ab 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -712,6 +712,7 @@ class ProductCartItem extends React.PureComponent { key={"processed_options" + index} id={"processed_options" + index} target={((outvar, value) => { + console.log(outvar, value); options_data[outvar] = value; this.setState(options_data); })} diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index be43d9f..4e94edd 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -143,6 +143,69 @@ function LineWrapper(target, id, data, {title, fallback, outvar}) { return ; } +class SwitchLine extends Component { + constructor(props) { + super(props); + // Initialize the state object with the initial values from the props + this.state = { + text: props.outvar in props.data ? props.data[props.outvar].text : (props.fallback ? props.fallback.text : ""), + checked: props.outvar in props.data ? props.data[props.outvar].checked : (props.fallback ? props.fallback.checked : false) + }; + // Bind the event handler to this + this.handleText = this.handleText.bind(this); + this.handleCheck = this.handleCheck.bind(this); + this.props.target(this.props.outvar, this.state); + } + + handleText(element) { + let new_state = { + ...this.state, + text: element.target.value + } + this.setState(new_state); + this.props.target(this.props.outvar, new_state); + } + + handleCheck() { + // Update the state object with the new value for outvar + let new_state = { + text: !this.state.checked ? this.state.text : "", + checked: !this.state.checked + } + this.setState(new_state); + this.props.target(this.props.outvar, new_state); + } + + render() { + let key = this.props.id + this.props.outvar; + return ( +
+ +
+ + +
+ +
+ ); + } +} + +function SwitchLineWrapper(target, id, data, {title, fallback, outvar}) { + return ; +} + + function UnimplementedComponent(type, id) { //console.error("Missing component with type:", type) @@ -153,6 +216,7 @@ const componentsList = { "Radio": RadioWrapper, "Switch": SwitchWrapper, "Line": LineWrapper, + "SwitchLine": SwitchLineWrapper, "Default": UnimplementedComponent, }; -- 2.42.0 From 4d5dd505ae4ed81209b8880a06a7d201b91c5bf1 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Fri, 18 Aug 2023 17:09:33 +0800 Subject: [PATCH 06/42] Fix add of useless options to JSON Signed-off-by: Egor Savkin --- static/js/shop.jsx | 21 +++++++++++---- static/js/shop_components.jsx | 51 +++++++++++++++++++++++------------ 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index ce4c4ab..c4b88da 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -711,11 +711,22 @@ class ProductCartItem extends React.PureComponent { data={options_data} key={"processed_options" + index} id={"processed_options" + index} - target={((outvar, value) => { - console.log(outvar, value); - options_data[outvar] = value; - this.setState(options_data); - })} + target={{ + construct: ((outvar, value) => { + //console.log("construct", outvar, value, options_data); + options_data[outvar] = value; + this.setState(options_data); + }), + update: ((outvar, value) => { + //console.log("update", outvar, value, options_data); + if (outvar in options_data) options_data[outvar] = value; + this.setState(options_data); + }), + unmount: ((outvar) => { + //console.log("delete", outvar); + delete options_data[outvar]; + }) + }} />
) : null } diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 4e94edd..f3be9d3 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -16,7 +16,11 @@ class Radio extends Component { // Bind the event handler to this this.handleClick = this.handleClick.bind(this); - this.props.target(this.props.outvar, this.state.variant); + this.props.target.construct(this.props.outvar, this.state.variant); + } + + componentWillUnmount() { + this.props.target.unmount(this.props.outvar); } handleClick(variant) { @@ -25,7 +29,7 @@ class Radio extends Component { ...this.state, variant: variant }); - this.props.target(this.props.outvar, variant); + this.props.target.update(this.props.outvar, variant); } render() { @@ -63,12 +67,16 @@ class Switch extends Component { super(props); // Initialize the state object with the initial values from the props this.state = { - checked: props.outvar in props.data ? props.data[props.outvar] : !!(props.fallback) + checked: props.outvar in props.data ? props.data[props.outvar] : !!(props.fallback) }; // Bind the event handler to this this.handleClick = this.handleClick.bind(this); - this.props.target(this.props.outvar, this.state.checked); + this.props.target.construct(this.props.outvar, this.state.checked); + } + + componentWillUnmount() { + this.props.target.unmount(this.props.outvar); } handleClick() { @@ -77,7 +85,7 @@ class Switch extends Component { this.setState({ checked: new_checked }); - this.props.target(this.props.outvar, new_checked); + this.props.target.update(this.props.outvar, new_checked); } render() { @@ -113,11 +121,15 @@ class Line extends Component { super(props); // Initialize the state object with the initial values from the props this.state = { - text: props.outvar in props.data ? props.data[props.outvar] : (props.fallback ? props.fallback : "") + text: props.outvar in props.data ? props.data[props.outvar] : (props.fallback ? props.fallback : "") }; // Bind the event handler to this this.handleClick = this.handleClick.bind(this); - this.props.target(this.props.outvar, this.state.text); + this.props.target.construct(this.props.outvar, this.state.text); + } + + componentWillUnmount() { + this.props.target.unmount(this.props.outvar); } handleClick(element) { @@ -125,7 +137,7 @@ class Line extends Component { this.setState({ text: text }); - this.props.target(this.props.outvar, text); + this.props.target.update(this.props.outvar, text); } render() { @@ -133,7 +145,8 @@ class Line extends Component { return (
- +
); } @@ -148,13 +161,17 @@ class SwitchLine extends Component { super(props); // Initialize the state object with the initial values from the props this.state = { - text: props.outvar in props.data ? props.data[props.outvar].text : (props.fallback ? props.fallback.text : ""), + text: props.outvar in props.data ? props.data[props.outvar].text : (props.fallback ? props.fallback.text : ""), checked: props.outvar in props.data ? props.data[props.outvar].checked : (props.fallback ? props.fallback.checked : false) }; // Bind the event handler to this this.handleText = this.handleText.bind(this); this.handleCheck = this.handleCheck.bind(this); - this.props.target(this.props.outvar, this.state); + this.props.target.construct(this.props.outvar, this.state); + } + + componentWillUnmount() { + this.props.target.unmount(this.props.outvar); } handleText(element) { @@ -163,7 +180,7 @@ class SwitchLine extends Component { text: element.target.value } this.setState(new_state); - this.props.target(this.props.outvar, new_state); + this.props.target.update(this.props.outvar, new_state); } handleCheck() { @@ -173,7 +190,7 @@ class SwitchLine extends Component { checked: !this.state.checked } this.setState(new_state); - this.props.target(this.props.outvar, new_state); + this.props.target.update(this.props.outvar, new_state); } render() { @@ -186,16 +203,17 @@ class SwitchLine extends Component { className="form-check-input" type="checkbox" role="switch" - id={key+"switch"} + id={key + "switch"} checked={this.state.checked} onClick={this.handleCheck} onChange={this.handleCheck} /> -
- +
); } @@ -206,7 +224,6 @@ function SwitchLineWrapper(target, id, data, {title, fallback, outvar}) { } - function UnimplementedComponent(type, id) { //console.error("Missing component with type:", type) return
UNIMPLEMENTED
-- 2.42.0 From d72a295aa568bb079fe57cdbd958048b9df19bd5 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Fri, 18 Aug 2023 17:34:52 +0800 Subject: [PATCH 07/42] Adjust styles Signed-off-by: Egor Savkin --- sass/css/_shop.scss | 11 +++++++++-- static/js/shop.jsx | 2 +- static/js/shop_components.jsx | 3 +-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index 1e04278..3e88ff8 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -468,10 +468,13 @@ button { top: 0; width: 100%; min-height: 70px; + max-height: 350px; + overflow-y: scroll; position: absolute; display: flex; - align-items: center; - justify-content: center; + align-items: start; + justify-content: left; + text-align: left; background-color: white; color: black; flex-direction: column; @@ -481,6 +484,10 @@ button { font-size: .65rem; margin: 0; } + + div { + margin: 0 0.2rem; + } } } diff --git a/static/js/shop.jsx b/static/js/shop.jsx index c4b88da..4a193a8 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -703,7 +703,7 @@ class ProductCartItem extends React.PureComponent { {options ? (
+
@@ -197,7 +197,6 @@ class SwitchLine extends Component { let key = this.props.id + this.props.outvar; return (
-
Date: Mon, 21 Aug 2023 12:38:17 +0800 Subject: [PATCH 08/42] Make the design more compact Signed-off-by: Egor Savkin --- sass/css/_shop.scss | 19 +++++++++++++++++-- static/js/shop_components.jsx | 8 ++++---- static/js/shop_data.js | 9 +-------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index 3e88ff8..cfc8a83 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -468,7 +468,7 @@ button { top: 0; width: 100%; min-height: 70px; - max-height: 350px; + max-height: 320px; overflow-y: scroll; position: absolute; display: flex; @@ -486,7 +486,22 @@ button { } div { - margin: 0 0.2rem; + margin: 0.1rem 0.2rem; + font-size: 0.75rem; + + input { + padding: 0; + font-size: 0.75rem; + line-height: 1.1; + } + + label { + margin-bottom: 0.1rem; + } + } + + .form-check { + min-height: 1rem; } } diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index dca4728..d1aeeb8 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -36,7 +36,7 @@ class Radio extends Component { let key = this.props.id + this.props.outvar; return (
- {this.props.title} +
{this.props.title}
{this.props.variants.map((variant, _) => (
-
); @@ -186,7 +186,7 @@ class SwitchLine extends Component { handleCheck() { // Update the state object with the new value for outvar let new_state = { - text: !this.state.checked ? this.state.text : "", + ...this.state, checked: !this.state.checked } this.setState(new_state); @@ -211,7 +211,7 @@ class SwitchLine extends Component { {this.props.title}
-
); diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 6da3d7b..cef0628 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -79,14 +79,7 @@ const shop_data = { {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "MAC", outvar: "mac"}}, - {type: "Switch", args: {title: "Ext CLK", outvar: "ext_clk"}}, - { - "if": [ - {"===": [{"var": "ext_clk"}, true]}, - {type: "Line", args: {title: "Frequency", outvar: "ext_clk_freq", fallback: "125 MHz"}}, - null - ] - } + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, ], null ] -- 2.42.0 From 288a0cc74c4c4a28f1a75e6611805c11de248f07 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 22 Aug 2023 10:21:44 +0800 Subject: [PATCH 09/42] Make overlay appear on button click And fix options absense for non-carrier cards Signed-off-by: Egor Savkin --- sass/css/_shop.scss | 16 ++++-- static/images/shop/icon-customize.svg | 47 ++++++++++++++++++ static/js/shop.jsx | 71 ++++++++++++--------------- static/js/shop_components.jsx | 27 +++++++++- static/js/shop_data.js | 30 +++++++++++ 5 files changed, 146 insertions(+), 45 deletions(-) create mode 100644 static/images/shop/icon-customize.svg diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index cfc8a83..8e008d3 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -255,7 +255,7 @@ button { .item-card-name, .price { - > .alert-warning, > .alert-info { + > .alert-warning, .alert-info { background-color: inherit; height: inherit; width: 20px; @@ -432,7 +432,7 @@ button { height: 24px; } - > .alert-warning, > .alert-info { + > .alert-warning, .alert-info { background-color: inherit; height: inherit; width: 20px; @@ -465,15 +465,15 @@ button { } .overlayVariant { - top: 0; - width: 100%; + top: 24px; + width: 132px; min-height: 70px; max-height: 320px; overflow-y: scroll; position: absolute; display: flex; align-items: start; - justify-content: left; + justify-content: center; text-align: left; background-color: white; color: black; @@ -504,7 +504,13 @@ button { min-height: 1rem; } } + } + .overlay-smallcard { + right: -34.5px; + } + .overlay-bigcard { + right: -3px; } .hovered { diff --git a/static/images/shop/icon-customize.svg b/static/images/shop/icon-customize.svg new file mode 100644 index 0000000..cee836b --- /dev/null +++ b/static/images/shop/icon-customize.svg @@ -0,0 +1,47 @@ + + diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 4a193a8..d0dcff0 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -6,7 +6,7 @@ import { createRoot } from "react-dom/client"; import PropTypes from "prop-types"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { v4 as uuidv4 } from 'uuid'; -import ProcessOptions from "./shop_components.jsx"; +import { CustomizeButton } from "./shop_components.jsx"; import { OverlayTrigger } from "react-bootstrap"; @@ -699,37 +699,31 @@ class ProductCartItem extends React.PureComponent { {warning ? ( - ) : (options ? : null) } + ) : (options ? ( { + //console.log("construct", outvar, value, options_data); + options_data[outvar] = value; + this.setState(options_data); + }), + update: ((outvar, value) => { + //console.log("update", outvar, value, options_data); + if (outvar in options_data) options_data[outvar] = value; + this.setState(options_data); + }), + unmount: ((outvar) => { + //console.log("delete", outvar); + delete options_data[outvar]; + }) + }} + />) : null) } - {options ? ( -
- { - //console.log("construct", outvar, value, options_data); - options_data[outvar] = value; - this.setState(options_data); - }), - update: ((outvar, value) => { - //console.log("update", outvar, value, options_data); - if (outvar in options_data) options_data[outvar] = value; - this.setState(options_data); - }), - unmount: ((outvar) => { - //console.log("delete", outvar); - delete options_data[outvar]; - }) - }} - /> -
- ) : null } {warning && model.showWarning && (
@@ -1428,8 +1422,7 @@ class OrderSumary extends React.PureComponent { {summary.map((item, index) => { - let alert; - let warning; + let alert, warning, options; if (itemsData[index] && itemsData[index].warnings) { alert = itemsData[index]; @@ -1438,6 +1431,7 @@ class OrderSumary extends React.PureComponent { warning = alert.warnings[warningsKeys[0]]; } } + options = itemsData[index] && itemsData[index].options; return ( - ) : ( - + />) : null )} - {!warning && ( + {(!warning && !options) && ( { - if (!(idx in itemsData)) itemsData[idx] = {}; + itemsCloned.forEach((elem, idx) => { + if (!(idx in itemsData)) itemsData[idx] = elem; if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) { itemsData[idx].options_data = this.state.columns.cart.itemsData[idx].options_data; } }); - // update state with rules this.setState({ ...this.state, diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index d1aeeb8..bee55cb 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -2,6 +2,7 @@ import React, {Component} from "react"; import jsonLogic from 'json-logic-js'; +import { useState } from 'react'; // https://stackoverflow.com/a/70511311 const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); @@ -263,4 +264,28 @@ export default function ProcessOptions({options, data, target, id}) { return ProcessOptions({options: jsonLogic.apply(options, data), data: data, target: target, id: id}); } } -} \ No newline at end of file +} + +export function CustomizeButton({options, data, target, id, big}) { + const [show, setShow] = useState(false); + + let div_classes = "overlayVariant border rounded " + (big ? "overlay-bigcard" : "overlay-smallcard") + const handleClick = (event) => { + setShow(!show); + }; + + return ( +
+ +
+ +
+
+ ); +} diff --git a/static/js/shop_data.js b/static/js/shop_data.js index cef0628..6dcfbeb 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -147,6 +147,28 @@ const shop_data = { nbrCurrentClock: 0, slotOccupied: 1, clockOccupied: 0, + options: [ + {type: "Radio", args: {title: "Variant", outvar: "variant", variants: ["standalone", "master", "satellite"]}}, + { + "if": [ + { + "in": [ + {"var": "variant"}, [ + "master", "standalone" + ] + ] + }, + [ + {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24"}}, + {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, + {type: "SwitchLine", args: {title: "MAC", outvar: "mac"}}, + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, + ], + null + ] + }, + null + ], rules: { maxSlot: { type: 'kaslisoc-max-slot', @@ -262,6 +284,10 @@ const shop_data = { nbrClockMax: 0, slotOccupied: 1, clockOccupied: 0, + options: [ + {type: "Switch", args: {title: "Output upper bank", outvar: "upper_bank"}}, + {type: "Switch", args: {title: "Output lower bank", outvar: "lower_bank", fallback: true}} + ], rules: { resources: { type: 'bnc-dio', @@ -283,6 +309,10 @@ const shop_data = { ], datasheet_file: '/docs/sinara-datasheets/2118-2128.pdf', datasheet_name: '2118/2128 BNC/SMA-TTL datasheet', + options: [ + {type: "Switch", args: {title: "Output upper bank", outvar: "upper_bank"}}, + {type: "Switch", args: {title: "Output lower bank", outvar: "lower_bank", fallback: true}} + ], size: 'small', type: null, hp: 4, -- 2.42.0 From 23c750835897a8a9aae63c4ed56215dda314cac9 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 22 Aug 2023 12:41:32 +0800 Subject: [PATCH 10/42] Add popover for cart summary with options data Signed-off-by: Egor Savkin --- sass/css/_shop.scss | 23 ++++++++++++++++++ static/js/shop.jsx | 16 ++++-------- static/js/shop_components.jsx | 46 +++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index 8e008d3..e217d25 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -261,6 +261,29 @@ button { width: 20px; padding-bottom: 3px; } + .alert-info { + padding-bottom: 0; + } + } + + .overlayVariant { + min-width: 100px; + height: 150px; + overflow-y: scroll; + position: absolute; + display: flex; + align-items: start; + justify-content: center; + text-align: left; + background-color: white; + color: black; + flex-direction: column; + cursor: pointer; + + p { + font-size: .875rem; + margin: 0; + } } thead, tbody, tfoot { diff --git a/static/js/shop.jsx b/static/js/shop.jsx index d0dcff0..a62b4f7 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -6,9 +6,7 @@ import { createRoot } from "react-dom/client"; import PropTypes from "prop-types"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { v4 as uuidv4 } from 'uuid'; -import { CustomizeButton } from "./shop_components.jsx"; -import { OverlayTrigger } from "react-bootstrap"; - +import { CustomizeButton, CustomizeData } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; const data = window.shop_data; const itemsUnfoldedList = Array.from(data.columns.backlog.categories.map(groupId => groupId.itemIds).flat()); @@ -1422,7 +1420,7 @@ class OrderSumary extends React.PureComponent { {summary.map((item, index) => { - let alert, warning, options; + let alert, warning, options, options_data; if (itemsData[index] && itemsData[index].warnings) { alert = itemsData[index]; @@ -1432,6 +1430,7 @@ class OrderSumary extends React.PureComponent { } } options = itemsData[index] && itemsData[index].options; + options_data = itemsData[index] && itemsData[index].options_data; return ( - ) : ( options ? - () : null + ) : ( (options && options_data) ? + ( ) : null )} {(!warning && !options) && ( @@ -1831,7 +1826,6 @@ class Shop extends React.PureComponent { }; const clonedCart = Array.from(this.state.columns.cart.items); const clonedCartData = Array.from(this.state.columns.cart.itemsData); - console.log(clonedCartData); for (const i in clonedCart) { const item = clonedCart[i]; const item_data = clonedCartData[i]; diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index bee55cb..4e6c154 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -2,11 +2,12 @@ import React, {Component} from "react"; import jsonLogic from 'json-logic-js'; -import { useState } from 'react'; +import {useState} from 'react'; // https://stackoverflow.com/a/70511311 const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); + class Radio extends Component { constructor(props) { super(props); @@ -276,7 +277,8 @@ export function CustomizeButton({options, data, target, id, big}) { return (
- +
); } + +export function CustomizeData({id, data}) { + const [show, setShow] = useState(false); + const [position, setPosition] = useState({x: 0, y: 0}); + + const handleClick = (event) => { + setPosition({x: event.clientX, y: event.clientY}); + setShow(!show); + }; + + const stringify = (value) => { + let value_type = trueTypeOf(value); + if (value_type === "string") { + return value; + } else if (value_type === "object") { + if (value.checked === false) { + return "off"; + } else if (value.checked === true && value.text) { + return value.text; + } + } + return JSON.stringify(value); + } + + return ( +
+ +
+
+ {Array.from(Object.entries(data).map(([key, value], _) => { + return (

{key}: {stringify(value)}

); + }))} +
+
+
+ ); +} + -- 2.42.0 From 894c1d2e14539bcb4ec4f7c6a7233bf52572e8ac Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 22 Aug 2023 17:39:18 +0800 Subject: [PATCH 11/42] Update bundle file Add custom options to more cards Minor design adjustments: add margin-left to icon and optimize the icon Signed-off-by: Egor Savkin --- package-lock.json | 7 ++-- static/images/shop/icon-customize.svg | 48 +--------------------- static/js/shop_components.jsx | 1 + static/js/shop_data.js | 59 +++++++++++++++++++++++---- 4 files changed, 56 insertions(+), 59 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77875ba..cb9ec6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,6 @@ "": { "name": "m-labs-zola", "version": "1.0.0", - "dependencies": { - "json-logic-js": "^2.0.2" - }, "devDependencies": { "@babel/cli": "^7.22.6", "@babel/core": "^7.22.8", @@ -20,6 +17,7 @@ "babel-preset-minify": "^0.5.2", "bootstrap": "^5.3.0", "jquery": "^3.7.0", + "json-logic-js": "^2.0.2", "prop-types": "^15.8.1", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.1", @@ -3661,7 +3659,8 @@ "node_modules/json-logic-js": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/json-logic-js/-/json-logic-js-2.0.2.tgz", - "integrity": "sha512-ZBtBdMJieqQcH7IX/LaBsr5pX+Y5JIW+EhejtM3Ffg2jdN9Iwf+Ht6TbHnvAZ/YtwyuhPaCBlnvzrwVeWdvGDQ==" + "integrity": "sha512-ZBtBdMJieqQcH7IX/LaBsr5pX+Y5JIW+EhejtM3Ffg2jdN9Iwf+Ht6TbHnvAZ/YtwyuhPaCBlnvzrwVeWdvGDQ==", + "dev": true }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", diff --git a/static/images/shop/icon-customize.svg b/static/images/shop/icon-customize.svg index cee836b..43a4c44 100644 --- a/static/images/shop/icon-customize.svg +++ b/static/images/shop/icon-customize.svg @@ -1,47 +1 @@ - - + diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 4e6c154..a63e691 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -318,6 +318,7 @@ export function CustomizeData({id, data}) { return (
diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 6dcfbeb..b645a62 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -83,8 +83,7 @@ const shop_data = { ], null ] - }, - null + } ], rules: { maxSlot: { @@ -166,8 +165,7 @@ const shop_data = { ], null ] - }, - null + } ], rules: { maxSlot: { @@ -285,8 +283,8 @@ const shop_data = { slotOccupied: 1, clockOccupied: 0, options: [ - {type: "Switch", args: {title: "Output upper bank", outvar: "upper_bank"}}, - {type: "Switch", args: {title: "Output lower bank", outvar: "lower_bank", fallback: true}} + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group"}}, + {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true}} ], rules: { resources: { @@ -310,8 +308,8 @@ const shop_data = { datasheet_file: '/docs/sinara-datasheets/2118-2128.pdf', datasheet_name: '2118/2128 BNC/SMA-TTL datasheet', options: [ - {type: "Switch", args: {title: "Output upper bank", outvar: "upper_bank"}}, - {type: "Switch", args: {title: "Output lower bank", outvar: "lower_bank", fallback: true}} + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group"}}, + {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true}} ], size: 'small', type: null, @@ -346,6 +344,12 @@ const shop_data = { ], datasheet_file: '/docs/sinara-datasheets/2238.pdf', datasheet_name: '2238 MCX-TTL datasheet', + options: [ + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group"}}, + {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true}}, + {type: "Switch", args: {title: "Output third group", outvar: "out_third_group", fallback: true}}, + {type: "Switch", args: {title: "Output fourth group", outvar: "out_fourth_group", fallback: true}} + ], size: 'small', type: null, hp: 4, @@ -416,6 +420,30 @@ const shop_data = { ], datasheet_file: '/docs/sinara-datasheets/4410-4412.pdf', datasheet_name: '4410/4412 Urukul datasheet', + options: [ + {type: "Switch", args: {title: "AD9912 instead of AD9910", outvar: "ad9912"}}, + { + "if": [ + {"var": "ad9912"}, + [ + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, + ], + [ + {type: "Switch", args: {title: "Synchronization", outvar: "sync"}}, + { + "if": [ + {"var": "sync"}, + null, + [ + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, + {type: "Switch", args: {title: "SUServo mode", outvar: "suservo"}} + ] + ] + } + ] + ] + } + ], size: 'small', type: 'urukul', hp: 4, @@ -461,6 +489,9 @@ const shop_data = { 'Internal MMCX clock from Kasli/Clocker and external SMA.', 'The upconverter is optional, if you would like the baseband version please leave us a note.' ], + options: [ + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}} + ], size: 'small', type: 'urukul', hp: 4, @@ -714,6 +745,9 @@ const shop_data = { 'Full-scale input ranges between +-10mV and +-10V.', 'Supports SU-Servo laser intensity stabilization servo in conjunction with Urukul.' ], + options: [ + {type: "Switch", args: {title: "SUServo mode", outvar: "suservo"}} + ], size: 'big', type: 'novo', hp: 8, @@ -788,6 +822,9 @@ const shop_data = { 'Frequency up to 1GHz.', 'Low jitter <100fs RMS.' ], + options: [ + {type: "Switch", args: {title: "Ext CLK", outvar: "ext_clk"}} + ], size: 'small', type: 'clocker', hp: 4, @@ -850,6 +887,9 @@ const shop_data = { 'Lower jitter and phase noise.', 'Large frequency changes take several milliseconds.', ], + options: [ + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}} + ], size: 'small', type: null, hp: 4, @@ -879,6 +919,9 @@ const shop_data = { 'Additional 4 channels up to 12 GHz.', 'Each Almazny channel outputs twice the frequency of its corresponding Mirny channel.', ], + options: [ + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}} + ], size: 'big', type: null, hp: 8, -- 2.42.0 From 0fe665c0bac0ae6cae78ffc19688b725c5b1bd0a Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 23 Aug 2023 12:58:13 +0800 Subject: [PATCH 12/42] Hide popups on clicking outside of them Signed-off-by: Egor Savkin --- package-lock.json | 230 +++------------------------------- package.json | 2 +- static/js/shop.jsx | 3 +- static/js/shop_components.jsx | 9 +- 4 files changed, 23 insertions(+), 221 deletions(-) diff --git a/package-lock.json b/package-lock.json index cb9ec6e..5db3e1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@babel/core": "^7.22.8", "@babel/preset-env": "^7.22.7", "@babel/preset-react": "^7.22.5", + "@uidotdev/usehooks": "^2.1.1", "axios": "^1.4.0", "babel-loader": "^9.1.3", "babel-preset-minify": "^0.5.2", @@ -21,7 +22,6 @@ "prop-types": "^15.8.1", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.1", - "react-bootstrap": "^2.8.0", "react-dom": "^18.2.0", "uuid": "^9.0.0", "webpack": "^5.88.1", @@ -1924,77 +1924,12 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "dev": true, + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" } }, - "node_modules/@react-aria/ssr": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.8.0.tgz", - "integrity": "sha512-Y54xs483rglN5DxbwfCPHxnkvZ+gZ0LbSYmR72LyWPGft8hN/lrl1VRS1EW2SMjnkEWlj+Km2mwvA3kEHDUA0A==", - "dev": true, - "dependencies": { - "@swc/helpers": "^0.5.0" - }, - "engines": { - "node": ">= 12" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" - } - }, - "node_modules/@restart/hooks": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.11.tgz", - "integrity": "sha512-Ft/ncTULZN6ldGHiF/k5qt72O8JyRMOeg0tApvCni8LkoiEahO+z3TNxfXIVGy890YtWVDvJAl662dVJSJXvMw==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@restart/ui": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz", - "integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.21.0", - "@popperjs/core": "^2.11.6", - "@react-aria/ssr": "^3.5.0", - "@restart/hooks": "^0.4.9", - "@types/warning": "^3.0.0", - "dequal": "^2.0.3", - "dom-helpers": "^5.2.0", - "uncontrollable": "^8.0.1", - "warning": "^4.0.3" - }, - "peerDependencies": { - "react": ">=16.14.0", - "react-dom": ">=16.14.0" - } - }, - "node_modules/@restart/ui/node_modules/uncontrollable": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", - "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", - "dev": true, - "peerDependencies": { - "react": ">=16.14.0" - } - }, - "node_modules/@swc/helpers": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.3.tgz", - "integrity": "sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/eslint": { "version": "8.44.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", @@ -2072,26 +2007,24 @@ "redux": "^4.0.0" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.8.tgz", - "integrity": "sha512-QmQ22q+Pb+HQSn04NL3HtrqHwYMf4h3QKArOy5F8U5nEVMaihBs3SR10WiOM1iwPz5jIo8x/u11al+iEGZZrvg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/scheduler": { "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", "dev": true }, - "node_modules/@types/warning": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.2.tgz", - "integrity": "sha512-S/2+OjBIcBl8Kur23YLe0hG1e7J5m2bHfB4UuMNoLZjIFhQWhTf1FeS+WFoXHUC6QsCEfk4pftj4J1KIKC1glA==", - "dev": true + "node_modules/@uidotdev/usehooks": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.1.1.tgz", + "integrity": "sha512-sVJ1jXU62Edh22dREEa3mHcHnH2MUgokuzLw9guNS30ADCkdhYASNZxg2V8iB83iwY5H+jSeSxjqGaFvsRrNBQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } }, "node_modules/@webassemblyjs/ast": { "version": "1.11.6", @@ -2866,12 +2799,6 @@ "node": ">=6.0" } }, - "node_modules/classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==", - "dev": true - }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -3017,25 +2944,6 @@ "node": ">=0.4.0" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, "node_modules/electron-to-chromium": { "version": "1.4.454", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.454.tgz", @@ -3500,15 +3408,6 @@ "node": ">=10.13.0" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3982,25 +3881,6 @@ "react-is": "^16.13.1" } }, - "node_modules/prop-types-extra": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", - "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", - "dev": true, - "dependencies": { - "react-is": "^16.3.2", - "warning": "^4.0.0" - }, - "peerDependencies": { - "react": ">=0.14.0" - } - }, - "node_modules/prop-types-extra/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -4068,36 +3948,6 @@ "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-bootstrap": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.9.1.tgz", - "integrity": "sha512-ezgmh/ARCYp18LbZEqPp0ppvy+ytCmycDORqc8vXSKYV3cer4VH7OReV8uMOoKXmYzivJTxgzGHalGrHamryHA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.22.5", - "@restart/hooks": "^0.4.9", - "@restart/ui": "^1.6.6", - "@types/react-transition-group": "^4.4.6", - "classnames": "^2.3.2", - "dom-helpers": "^5.2.1", - "invariant": "^2.2.4", - "prop-types": "^15.8.1", - "prop-types-extra": "^1.1.0", - "react-transition-group": "^4.4.5", - "uncontrollable": "^7.2.1", - "warning": "^4.0.3" - }, - "peerDependencies": { - "@types/react": ">=16.14.8", - "react": ">=16.14.0", - "react-dom": ">=16.14.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -4117,12 +3967,6 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "node_modules/react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", - "dev": true - }, "node_modules/react-redux": { "version": "7.2.9", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", @@ -4148,22 +3992,6 @@ } } }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4597,27 +4425,6 @@ "node": ">=8.0" } }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/uncontrollable": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", - "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.6.3", - "@types/react": ">=16.9.11", - "invariant": "^2.2.4", - "react-lifecycles-compat": "^3.0.4" - }, - "peerDependencies": { - "react": ">=15.0.0" - } - }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -4715,15 +4522,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/package.json b/package.json index 382b8e8..664e7ce 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "webpack": "^5.88.1", "webpack-cli": "^5.1.4", "json-logic-js": "^2.0.2", - "react-bootstrap": "^2.8.0" + "@uidotdev/usehooks": "^2.1.1" }, "babel": { "presets": [ diff --git a/static/js/shop.jsx b/static/js/shop.jsx index a62b4f7..8c09912 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -1290,7 +1290,8 @@ class OrderForm extends React.PureComponent { className="btn btn-outline-primary w-100 m-0 mb-2 mb-sm-0 me-sm-2" style={{'cursor': 'pointer', 'fontWeight': '700'}} defaultValue="Show JSON" - onClick={onClickShow} /> + onClick={onClickShow} + readOnly={true} />
diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index a63e691..7d6f52c 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -3,6 +3,7 @@ import React, {Component} from "react"; import jsonLogic from 'json-logic-js'; import {useState} from 'react'; +import {useClickAway} from "@uidotdev/usehooks"; // https://stackoverflow.com/a/70511311 const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); @@ -239,7 +240,7 @@ const componentsList = { }; -export default function ProcessOptions({options, data, target, id}) { +export function ProcessOptions({options, data, target, id}) { let options_t = trueTypeOf(options); if (options_t === "array") { @@ -269,6 +270,7 @@ export default function ProcessOptions({options, data, target, id}) { export function CustomizeButton({options, data, target, id, big}) { const [show, setShow] = useState(false); + const ref = useClickAway(() => setShow(false)); let div_classes = "overlayVariant border rounded " + (big ? "overlay-bigcard" : "overlay-smallcard") const handleClick = (event) => { @@ -276,7 +278,7 @@ export function CustomizeButton({options, data, target, id, big}) { }; return ( -
+
@@ -295,6 +297,7 @@ export function CustomizeButton({options, data, target, id, big}) { export function CustomizeData({id, data}) { const [show, setShow] = useState(false); const [position, setPosition] = useState({x: 0, y: 0}); + const ref = useClickAway(() => setShow(false)); const handleClick = (event) => { setPosition({x: event.clientX, y: event.clientY}); @@ -316,7 +319,7 @@ export function CustomizeData({id, data}) { } return ( -
+
-- 2.42.0 From 8bdfedc4b8c3dfaa4aae62bb4fd31d22a6e99449 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 23 Aug 2023 16:58:02 +0800 Subject: [PATCH 13/42] Reposition summary popup relative to icon respective to window width, hide on scroll Signed-off-by: Egor Savkin --- static/js/shop.jsx | 6 ++-- static/js/shop_components.jsx | 53 ++++++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 8c09912..72e9901 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -6,7 +6,7 @@ import { createRoot } from "react-dom/client"; import PropTypes from "prop-types"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { v4 as uuidv4 } from 'uuid'; -import { CustomizeButton, CustomizeData } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; +import { OptionsDialogPopup, OptionsSummaryPopup } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; const data = window.shop_data; const itemsUnfoldedList = Array.from(data.columns.backlog.categories.map(groupId => groupId.itemIds).flat()); @@ -697,7 +697,7 @@ class ProductCartItem extends React.PureComponent { {warning ? ( - ) : (options ? ( ) : ( (options && options_data) ? - ( ) : null + ( ) : null )} {(!warning && !options) && ( diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 7d6f52c..0e2ae15 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -2,7 +2,7 @@ import React, {Component} from "react"; import jsonLogic from 'json-logic-js'; -import {useState} from 'react'; +import {useState, useEffect} from 'react'; import {useClickAway} from "@uidotdev/usehooks"; // https://stackoverflow.com/a/70511311 @@ -268,7 +268,7 @@ export function ProcessOptions({options, data, target, id}) { } } -export function CustomizeButton({options, data, target, id, big}) { +export function OptionsDialogPopup({options, data, target, id, big}) { const [show, setShow] = useState(false); const ref = useClickAway(() => setShow(false)); @@ -294,14 +294,51 @@ export function CustomizeButton({options, data, target, id, big}) { ); } -export function CustomizeData({id, data}) { +export function OptionsSummaryPopup({id, data}) { const [show, setShow] = useState(false); const [position, setPosition] = useState({x: 0, y: 0}); - const ref = useClickAway(() => setShow(false)); + const [size, setSize] = useState({w: 0, h: 0}); + const close = () => { + setShow(false); + document.removeEventListener("scroll", close, true); + } + + const ref = useClickAway(close); + + const reposition = () => { + let popup_button = document.getElementById(id + "img"); + let rect = popup_button.getBoundingClientRect() + let pos_x = (rect.left + rect.right) / 2; + let pos_y = (rect.top + rect.bottom) / 2; + if (pos_x + size.w > window.innerWidth) { + setPosition({x: pos_x - size.w - 20, y: pos_y - size.h / 2}); + } else { + setPosition({x: pos_x - size.w / 2, y: pos_y - size.h - 20}); + } + } + + useEffect(() => { + if (show) { + let popup = document.getElementById(id); + let width = popup.offsetWidth; + let height = popup.offsetHeight; + setSize({w: width, h: height}); + reposition() + } + }, [show]) + + + useEffect(() => { + if (show) { + reposition(); + } + }, [show, size]) const handleClick = (event) => { - setPosition({x: event.clientX, y: event.clientY}); setShow(!show); + if (!show) { + document.addEventListener("scroll", close, true); + } }; const stringify = (value) => { @@ -322,9 +359,11 @@ export function CustomizeData({id, data}) {
-
+
{Array.from(Object.entries(data).map(([key, value], _) => { return (

{key}: {stringify(value)}

); -- 2.42.0 From 0df69499b8749da472247f241aa749f36e122d83 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 23 Aug 2023 17:02:22 +0800 Subject: [PATCH 14/42] Remove MAC from options Signed-off-by: Egor Savkin --- static/js/shop_data.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/static/js/shop_data.js b/static/js/shop_data.js index b645a62..c20279e 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -78,7 +78,6 @@ const shop_data = { [ {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, - {type: "SwitchLine", args: {title: "MAC", outvar: "mac"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, ], null @@ -160,7 +159,6 @@ const shop_data = { [ {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, - {type: "SwitchLine", args: {title: "MAC", outvar: "mac"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, ], null -- 2.42.0 From 788653abaa122e3c45aab1bdd42d5023f00241f2 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 6 Sep 2023 14:22:26 +0800 Subject: [PATCH 15/42] Add icons to options titles Signed-off-by: Egor Savkin --- sass/css/_shop.scss | 6 ++++++ static/images/shop/icon-leaf.svg | 1 + static/js/shop_components.jsx | 30 +++++++++++++++++++----------- static/js/shop_data.js | 5 ++++- 4 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 static/images/shop/icon-leaf.svg diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index e217d25..1ff5801 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -521,6 +521,12 @@ button { label { margin-bottom: 0.1rem; } + + .options-icon { + display: inline; + height: .875rem; + margin-right: 0.2rem; + } } .form-check { diff --git a/static/images/shop/icon-leaf.svg b/static/images/shop/icon-leaf.svg new file mode 100644 index 0000000..f11ca49 --- /dev/null +++ b/static/images/shop/icon-leaf.svg @@ -0,0 +1 @@ + diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 0e2ae15..0eeecbe 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -39,7 +39,10 @@ class Radio extends Component { let key = this.props.id + this.props.outvar; return (
-
{this.props.title}
+
+ {this.props.icon ? : null} + {this.props.title} +
{this.props.variants.map((variant, _) => (
; +function RadioWrapper(target, id, data, {title, variants, outvar, icon}) { + return ; } class Switch extends Component { @@ -70,7 +73,7 @@ class Switch extends Component { super(props); // Initialize the state object with the initial values from the props this.state = { - checked: props.outvar in props.data ? props.data[props.outvar] : !!(props.fallback) + checked: props.outvar in props.data ? !!(props.data[props.outvar]) : !!(props.fallback) }; // Bind the event handler to this @@ -106,6 +109,7 @@ class Switch extends Component { onChange={this.handleClick} />
@@ -114,8 +118,8 @@ class Switch extends Component { } } -function SwitchWrapper(target, id, data, {title, fallback, outvar}) { - return ; +function SwitchWrapper(target, id, data, {title, fallback, outvar, icon}) { + return ; } @@ -147,7 +151,10 @@ class Line extends Component { let key = this.props.id + this.props.outvar; return (
- +
@@ -155,8 +162,8 @@ class Line extends Component { } } -function LineWrapper(target, id, data, {title, fallback, outvar}) { - return ; +function LineWrapper(target, id, data, {title, fallback, outvar, icon}) { + return ; } class SwitchLine extends Component { @@ -211,6 +218,7 @@ class SwitchLine extends Component { onChange={this.handleCheck} />
@@ -221,8 +229,8 @@ class SwitchLine extends Component { } } -function SwitchLineWrapper(target, id, data, {title, fallback, outvar}) { - return ; +function SwitchLineWrapper(target, id, data, {title, fallback, outvar, icon}) { + return ; } diff --git a/static/js/shop_data.js b/static/js/shop_data.js index c20279e..3c4bc15 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -79,8 +79,11 @@ const shop_data = { {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, + {type: "Switch", args: {title: "Email device_db", outvar: "out", icon: "/shop/icon-leaf.svg"}}, ], - null + [ + {type: "Switch", args: {title: "Optic fiber instead of copper cable", outvar: "optics"}} + ] ] } ], -- 2.42.0 From 8db77cf8c79dedea3350ca59b798e83898a39927 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 6 Sep 2023 16:43:51 +0800 Subject: [PATCH 16/42] Add tooltips with hints for the user Signed-off-by: Egor Savkin --- package-lock.json | 218 +++++++++++++++++++++++++++++++++- package.json | 1 + sass/css/_shop.scss | 1 + static/js/shop_components.jsx | 84 +++++++++++-- static/js/shop_data.js | 8 +- 5 files changed, 294 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5db3e1e..d5f7465 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "prop-types": "^15.8.1", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.1", + "react-bootstrap": "^2.8.0", "react-dom": "^18.2.0", "uuid": "^9.0.0", "webpack": "^5.88.1", @@ -1924,12 +1925,77 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "dev": true, - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" } }, + "node_modules/@react-aria/ssr": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.7.1.tgz", + "integrity": "sha512-ovVPSD1WlRpZHt7GI9DqJrWG3OIYS+NXQ9y5HIewMJpSe+jPQmMQfyRmgX4EnvmxSlp0u04Wg/7oItcoSIb/RA==", + "dev": true, + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.11.tgz", + "integrity": "sha512-Ft/ncTULZN6ldGHiF/k5qt72O8JyRMOeg0tApvCni8LkoiEahO+z3TNxfXIVGy890YtWVDvJAl662dVJSJXvMw==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz", + "integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.4.9", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", + "dev": true, + "peerDependencies": { + "react": ">=16.14.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", + "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/eslint": { "version": "8.44.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", @@ -2007,12 +2073,27 @@ "redux": "^4.0.0" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz", + "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/scheduler": { "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", "dev": true }, + "node_modules/@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==", + "dev": true + }, "node_modules/@uidotdev/usehooks": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.1.1.tgz", @@ -2799,6 +2880,12 @@ "node": ">=6.0" } }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==", + "dev": true + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -2944,6 +3031,25 @@ "node": ">=0.4.0" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.454", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.454.tgz", @@ -3408,6 +3514,15 @@ "node": ">=10.13.0" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3881,6 +3996,25 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "dev": true, + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/prop-types-extra/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -3948,6 +4082,36 @@ "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-bootstrap": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz", + "integrity": "sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.6.3", + "@types/react-transition-group": "^4.4.5", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -3967,6 +4131,12 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "dev": true + }, "node_modules/react-redux": { "version": "7.2.9", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", @@ -3992,6 +4162,22 @@ } } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4425,6 +4611,27 @@ "node": ">=8.0" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -4522,6 +4729,15 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/package.json b/package.json index 664e7ce..0bec725 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "jquery": "^3.7.0", "prop-types": "^15.8.1", "react": "^18.2.0", + "react-bootstrap": "^2.8.0", "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "uuid": "^9.0.0", diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index 1ff5801..97c475b 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -526,6 +526,7 @@ button { display: inline; height: .875rem; margin-right: 0.2rem; + margin-left: 0.2rem; } } diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 0eeecbe..f73259c 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -4,6 +4,7 @@ import React, {Component} from "react"; import jsonLogic from 'json-logic-js'; import {useState, useEffect} from 'react'; import {useClickAway} from "@uidotdev/usehooks"; +import {OverlayTrigger, Tooltip} from "react-bootstrap"; // https://stackoverflow.com/a/70511311 const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); @@ -40,9 +41,22 @@ class Radio extends Component { return (
- {this.props.icon ? : null} + {this.props.icon ? : null} {this.props.title}
+ { + this.props.tip ? + ( + {this.props.tip} + + }> + + ) + : + null + } {this.props.variants.map((variant, _) => (
; +function RadioWrapper(target, id, data, {title, variants, outvar, icon, tip}) { + return ; } class Switch extends Component { @@ -108,18 +123,32 @@ class Switch extends Component { onClick={this.handleClick} onChange={this.handleClick} /> -
); } } -function SwitchWrapper(target, id, data, {title, fallback, outvar, icon}) { - return ; +function SwitchWrapper(target, id, data, {title, fallback, outvar, icon, tip}) { + return ; } @@ -151,10 +180,24 @@ class Line extends Component { let key = this.props.id + this.props.outvar; return (
+ + { + this.props.tip ? + ( + {this.props.tip} + + }> + + ) + : + null + }
@@ -162,8 +205,9 @@ class Line extends Component { } } -function LineWrapper(target, id, data, {title, fallback, outvar, icon}) { - return ; +function LineWrapper(target, id, data, {title, fallback, outvar, icon, tip}) { + return ; } class SwitchLine extends Component { @@ -218,9 +262,22 @@ class SwitchLine extends Component { onChange={this.handleCheck} /> + { + this.props.tip ? + ( + {this.props.tip} + + }> + + ) + : + null + }
@@ -229,8 +286,9 @@ class SwitchLine extends Component { } } -function SwitchLineWrapper(target, id, data, {title, fallback, outvar, icon}) { - return ; +function SwitchLineWrapper(target, id, data, {title, fallback, outvar, icon, tip}) { + return ; } diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 3c4bc15..e6e4068 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -76,13 +76,13 @@ const shop_data = { ] }, [ - {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24"}}, + {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24", tip: "Set up IPv4 address used by core device"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, - {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, - {type: "Switch", args: {title: "Email device_db", outvar: "out", icon: "/shop/icon-leaf.svg"}}, + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}, tip: "Use external clock reference: 10, 80 (beta), 100 or 125 MHz. Other variants may be provided if needed."}}, + {type: "Switch", args: {title: "Email device_db", outvar: "out", icon: "/shop/icon-leaf.svg", tip: "Send the device_db.py file by email instead of USB-drive"}}, ], [ - {type: "Switch", args: {title: "Optic fiber instead of copper cable", outvar: "optics"}} + {type: "Switch", args: {title: "Optic fiber", outvar: "optics", tip: "Use optic fiber instead of direct attach copper cable"}} ] ] } -- 2.42.0 From a3075a5691dd32ccde3aa86832306d903fc47df5 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 6 Sep 2023 17:10:51 +0800 Subject: [PATCH 17/42] Use tips on more cards Signed-off-by: Egor Savkin --- static/js/shop_components.jsx | 8 +++---- static/js/shop_data.js | 41 +++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index f73259c..95c6fc3 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -15,7 +15,7 @@ class Radio extends Component { super(props); // Initialize the state object with the initial values from the props this.state = { - variant: props.outvar in props.data ? props.data[props.outvar] : props.variants[0], + variant: props.outvar in props.data ? props.data[props.outvar] : props.variants[ props.fallback ? props.fallback : 0 ], }; // Bind the event handler to this @@ -40,7 +40,7 @@ class Radio extends Component { let key = this.props.id + this.props.outvar; return (
-
+
{this.props.icon ? : null} {this.props.title}
@@ -78,8 +78,8 @@ class Radio extends Component { } } -function RadioWrapper(target, id, data, {title, variants, outvar, icon, tip}) { - return ; } diff --git a/static/js/shop_data.js b/static/js/shop_data.js index e6e4068..505327c 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -160,11 +160,14 @@ const shop_data = { ] }, [ - {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24"}}, + {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24", tip: "Set up IPv4 address used by core device"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, - {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}, tip: "Use external clock reference: 10, 80 (beta), 100 or 125 MHz. Other variants may be provided if needed."}}, + {type: "Switch", args: {title: "Email device_db", outvar: "out", icon: "/shop/icon-leaf.svg", tip: "Send the device_db.py file by email instead of USB-drive"}}, ], - null + [ + {type: "Switch", args: {title: "Optic fiber", outvar: "optics", tip: "Use optic fiber instead of direct attach copper cable"}} + ] ] } ], @@ -284,8 +287,8 @@ const shop_data = { slotOccupied: 1, clockOccupied: 0, options: [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group"}}, - {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true}} + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}}, + {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}} ], rules: { resources: { @@ -309,8 +312,8 @@ const shop_data = { datasheet_file: '/docs/sinara-datasheets/2118-2128.pdf', datasheet_name: '2118/2128 BNC/SMA-TTL datasheet', options: [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group"}}, - {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true}} + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}}, + {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}} ], size: 'small', type: null, @@ -346,10 +349,10 @@ const shop_data = { datasheet_file: '/docs/sinara-datasheets/2238.pdf', datasheet_name: '2238 MCX-TTL datasheet', options: [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group"}}, - {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true}}, - {type: "Switch", args: {title: "Output third group", outvar: "out_third_group", fallback: true}}, - {type: "Switch", args: {title: "Output fourth group", outvar: "out_fourth_group", fallback: true}} + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}}, + {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}}, + {type: "Switch", args: {title: "Output third group", outvar: "out_third_group", fallback: true, tip: "Switch connectors 8-11 to output"}}, + {type: "Switch", args: {title: "Output fourth group", outvar: "out_fourth_group", fallback: true, tip: "Switch connectors 12-15 to output"}} ], size: 'small', type: null, @@ -422,7 +425,7 @@ const shop_data = { datasheet_file: '/docs/sinara-datasheets/4410-4412.pdf', datasheet_name: '4410/4412 Urukul datasheet', options: [ - {type: "Switch", args: {title: "AD9912 instead of AD9910", outvar: "ad9912"}}, + {type: "Switch", args: {title: "AD9912", outvar: "ad9912", tip: "AD9912 chip instead of AD9910"}}, { "if": [ {"var": "ad9912"}, @@ -437,7 +440,7 @@ const shop_data = { null, [ {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, - {type: "Switch", args: {title: "SUServo mode", outvar: "suservo"}} + {type: "Switch", args: {title: "SUServo mode", outvar: "suservo", }} ] ] } @@ -786,6 +789,9 @@ const shop_data = { 'Existing stack supports summing over rectangular ROIs and reporting the result to ARTIQ kernels.', 'Camera signal is entirely processed in the Kasli FPGA.', ], + options: [ + {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', hp: 4, @@ -824,7 +830,8 @@ const shop_data = { 'Low jitter <100fs RMS.' ], options: [ - {type: "Switch", args: {title: "Ext CLK", outvar: "ext_clk"}} + {type: "Switch", args: {title: "Ext CLK", outvar: "ext_clk"}}, + {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: 'clocker', @@ -864,6 +871,9 @@ const shop_data = { '100Base-T Ethernet.', 'Can be controlled by Kasli or work stand-alone with PoE supply.' ], + options: [ + {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, hp: 4, @@ -1008,6 +1018,9 @@ const shop_data = { '2-channel Pound Drever Hall (PDH) lock generator.', 'AD9959 DDS (500MSPS, 10-bit).' ], + options: [ + {type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}} + ], size: 'big', type: null, hp: 8, -- 2.42.0 From b245655c411ae0c12d292aa0b302bedb7737c686 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Fri, 8 Sep 2023 15:39:38 +0800 Subject: [PATCH 18/42] Fix tooltip showed out when options overlay was closed Signed-off-by: esavkin --- static/js/shop_components.jsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 95c6fc3..3af8e87 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -15,7 +15,7 @@ class Radio extends Component { super(props); // Initialize the state object with the initial values from the props this.state = { - variant: props.outvar in props.data ? props.data[props.outvar] : props.variants[ props.fallback ? props.fallback : 0 ], + variant: props.outvar in props.data ? props.data[props.outvar] : props.variants[props.fallback ? props.fallback : 0], }; // Bind the event handler to this @@ -79,7 +79,8 @@ class Radio extends Component { } function RadioWrapper(target, id, data, {title, variants, outvar, fallback, icon, tip}) { - return ; } @@ -336,7 +337,11 @@ export function ProcessOptions({options, data, target, id}) { export function OptionsDialogPopup({options, data, target, id, big}) { const [show, setShow] = useState(false); - const ref = useClickAway(() => setShow(false)); + const ref = useClickAway((e) => { + if (e.type === "mousedown") // ignore touchstart + setShow(false) + } + ); let div_classes = "overlayVariant border rounded " + (big ? "overlay-bigcard" : "overlay-smallcard") const handleClick = (event) => { -- 2.42.0 From f67aa7fc51db1bde25d428d9edb9baddd17c7025 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Fri, 8 Sep 2023 18:27:23 +0800 Subject: [PATCH 19/42] Add external data for use per every card. Apply it for TTL and Suservo Signed-off-by: esavkin --- static/js/shop.jsx | 9 ++++-- static/js/shop_components.jsx | 16 +++++++++-- static/js/shop_data.js | 52 +++++++++++++++++++++++++++++++---- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 72e9901..12adf3f 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -6,7 +6,7 @@ import { createRoot } from "react-dom/client"; import PropTypes from "prop-types"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { v4 as uuidv4 } from 'uuid'; -import { OptionsDialogPopup, OptionsSummaryPopup } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; +import { OptionsDialogPopup, OptionsSummaryPopup, fill_ext_data } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; const data = window.shop_data; const itemsUnfoldedList = Array.from(data.columns.backlog.categories.map(groupId => groupId.itemIds).flat()); @@ -538,6 +538,7 @@ class ProductCartItem extends React.PureComponent { index: PropTypes.number.isRequired, model: PropTypes.object.isRequired, data: PropTypes.object, + ext_data: PropTypes.object, onToggleOverlayRemove: PropTypes.func, onClickRemoveItem: PropTypes.func, onClickItem: PropTypes.func, @@ -591,6 +592,7 @@ class ProductCartItem extends React.PureComponent { model, data, index, + ext_data, } = this.props; let warning, options, options_data; @@ -608,6 +610,7 @@ class ProductCartItem extends React.PureComponent { options = data.options; if (!data.options_data) data.options_data = {}; options_data = data.options_data; + options_data.ext_data = ext_data; } let render_progress; @@ -702,7 +705,7 @@ class ProductCartItem extends React.PureComponent { data={options_data} key={"popover" + index} id={"popover" + index} - big={data.size == "big"} + big={data.size === "big"} target={{ construct: ((outvar, value) => { //console.log("construct", outvar, value, options_data); @@ -867,6 +870,7 @@ class Cart extends React.PureComponent { const products = data.items.map((item, index) => { let itemData; + let ext_data = fill_ext_data(data.itemsData, index); if (data.itemsData && index in data.itemsData) { itemData = data.itemsData[index]; } @@ -880,6 +884,7 @@ class Cart extends React.PureComponent { id={item.id} index={index} data={itemData} + ext_data={ext_data} onToggleOverlayRemove={onToggleOverlayRemove} onClickRemoveItem={onClickRemoveItem} onClickItem={onClickItem} diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 3af8e87..c0d1224 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -436,12 +436,22 @@ export function OptionsSummaryPopup({id, data}) { className="overlayVariant card border rounded" id={id}>
- {Array.from(Object.entries(data).map(([key, value], _) => { - return (

{key}: {stringify(value)}

); - }))} + {Array.from(Object.entries(data) + .filter(([key, value], _) => key !== "ext_data") + .map(([key, value], _) => { + return (

{key}: {stringify(value)}

); + }))}
); } +export function fill_ext_data(data, index) { + return { + has_other_dio: data.filter((value, item_index) => index !== item_index && value.name.endsWith("-TTL")).length > 0, + has_dds: data.filter(((value, _) => value.name === "DDS" )).length > 0, + has_sampler: data.filter(((value, _) => value.name === "Sampler" )).length > 0 + } +} + diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 505327c..0e4c44e 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -287,7 +287,17 @@ const shop_data = { slotOccupied: 1, clockOccupied: 0, options: [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}}, + { + "if": [ + {"var": "ext_data.has_other_dio"}, + [ + {type: "Switch", args: {title: "Output first group", fallback: true, outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + ], + [ + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + ] + ] + }, {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}} ], rules: { @@ -312,7 +322,17 @@ const shop_data = { datasheet_file: '/docs/sinara-datasheets/2118-2128.pdf', datasheet_name: '2118/2128 BNC/SMA-TTL datasheet', options: [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}}, + { + "if": [ + {"var": "ext_data.has_other_dio"}, + [ + {type: "Switch", args: {title: "Output first group", fallback: true, outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + ], + [ + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + ] + ] + }, {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}} ], size: 'small', @@ -349,7 +369,17 @@ const shop_data = { datasheet_file: '/docs/sinara-datasheets/2238.pdf', datasheet_name: '2238 MCX-TTL datasheet', options: [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}}, + { + "if": [ + {"var": "ext_data.has_other_dio"}, + [ + {type: "Switch", args: {title: "Output first group", fallback: true, outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + ], + [ + {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + ] + ] + }, {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}}, {type: "Switch", args: {title: "Output third group", outvar: "out_third_group", fallback: true, tip: "Switch connectors 8-11 to output"}}, {type: "Switch", args: {title: "Output fourth group", outvar: "out_fourth_group", fallback: true, tip: "Switch connectors 12-15 to output"}} @@ -440,7 +470,13 @@ const shop_data = { null, [ {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, - {type: "Switch", args: {title: "SUServo mode", outvar: "suservo", }} + { + "if": [ + {"var": "ext_data.has_sampler"}, + {type: "Switch", args: {title: "SUServo mode", outvar: "suservo"}}, + null + ] + } ] ] } @@ -750,7 +786,13 @@ const shop_data = { 'Supports SU-Servo laser intensity stabilization servo in conjunction with Urukul.' ], options: [ - {type: "Switch", args: {title: "SUServo mode", outvar: "suservo"}} + { + "if": [ + {"var": "ext_data.has_dds"}, + {type: "Switch", args: {title: "SUServo mode", outvar: "suservo"}}, + null + ] + } ], size: 'big', type: 'novo', -- 2.42.0 From c55687e05a0077cef036a627a8bd6f8f7f43df4d Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Mon, 11 Sep 2023 17:38:40 +0800 Subject: [PATCH 20/42] Add groups of options and some fixes for long lists of options Signed-off-by: Egor Savkin --- sass/css/_shop.scss | 2 - static/js/shop_components.jsx | 13 ++++- static/js/shop_data.js | 106 ++++++++++++++++++++++++++++++++-- 3 files changed, 111 insertions(+), 10 deletions(-) diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index 97c475b..9a02dea 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -273,7 +273,6 @@ button { position: absolute; display: flex; align-items: start; - justify-content: center; text-align: left; background-color: white; color: black; @@ -496,7 +495,6 @@ button { position: absolute; display: flex; align-items: start; - justify-content: center; text-align: left; background-color: white; color: black; diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index c0d1224..b074edc 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -322,10 +322,15 @@ export function ProcessOptions({options, data, target, id}) { } else if (options_t === "object") { if ( trueTypeOf(options.type) === "string" && - trueTypeOf(options.args) === "object" + (trueTypeOf(options.args) === "object" || trueTypeOf(options.items) === "array") ) { if (options.type in componentsList) { return componentsList[options.type](target, id + options.type, data, options.args); + } else if (options.type === "Group") { + return ( +
+ { ProcessOptions({options: jsonLogic.apply(options.items, data), data: data, target: target, id: id}) } +
); } else { return componentsList["Default"](options.type, id + "missing"); } @@ -371,16 +376,18 @@ export function OptionsSummaryPopup({id, data}) { const [size, setSize] = useState({w: 0, h: 0}); const close = () => { setShow(false); - document.removeEventListener("scroll", close, true); + document.removeEventListener("scroll", reposition, true); } const ref = useClickAway(close); const reposition = () => { + console.trace("reposition") let popup_button = document.getElementById(id + "img"); let rect = popup_button.getBoundingClientRect() let pos_x = (rect.left + rect.right) / 2; let pos_y = (rect.top + rect.bottom) / 2; + console.trace("reposition", pos_x, pos_y) if (pos_x + size.w > window.innerWidth) { setPosition({x: pos_x - size.w - 20, y: pos_y - size.h / 2}); } else { @@ -408,7 +415,7 @@ export function OptionsSummaryPopup({id, data}) { const handleClick = (event) => { setShow(!show); if (!show) { - document.addEventListener("scroll", close, true); + document.addEventListener("scroll", reposition, true); } }; diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 0e4c44e..eebe791 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -79,7 +79,7 @@ const shop_data = { {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24", tip: "Set up IPv4 address used by core device"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}, tip: "Use external clock reference: 10, 80 (beta), 100 or 125 MHz. Other variants may be provided if needed."}}, - {type: "Switch", args: {title: "Email device_db", outvar: "out", icon: "/shop/icon-leaf.svg", tip: "Send the device_db.py file by email instead of USB-drive"}}, + {type: "Switch", args: {title: "Email device_db", outvar: "email_ddb", icon: "/shop/icon-leaf.svg", tip: "Send the device_db.py file by email instead of USB-drive"}}, ], [ {type: "Switch", args: {title: "Optic fiber", outvar: "optics", tip: "Use optic fiber instead of direct attach copper cable"}} @@ -163,7 +163,7 @@ const shop_data = { {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24", tip: "Set up IPv4 address used by core device"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}, tip: "Use external clock reference: 10, 80 (beta), 100 or 125 MHz. Other variants may be provided if needed."}}, - {type: "Switch", args: {title: "Email device_db", outvar: "out", icon: "/shop/icon-leaf.svg", tip: "Send the device_db.py file by email instead of USB-drive"}}, + {type: "Switch", args: {title: "Email device_db", outvar: "email_ddb", icon: "/shop/icon-leaf.svg", tip: "Send the device_db.py file by email instead of USB-drive"}}, ], [ {type: "Switch", args: {title: "Optic fiber", outvar: "optics", tip: "Use optic fiber instead of direct attach copper cable"}} @@ -298,7 +298,31 @@ const shop_data = { ] ] }, - {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}} + { + "if": [ + {"!": {"var": "out_first_group"}}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #0", fallback: true, outvar: "term_0", tip: "Enable termination on channel #0"}}, + {type: "Switch", args: {title: "Termination #1", fallback: true, outvar: "term_1", tip: "Enable termination on channel #1"}}, + {type: "Switch", args: {title: "Termination #2", fallback: true, outvar: "term_2", tip: "Enable termination on channel #2"}}, + {type: "Switch", args: {title: "Termination #3", fallback: true, outvar: "term_3", tip: "Enable termination on channel #3"}}, + ]}, + null + ] + }, + {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}}, + { + "if": [ + {"!": {"var": "out_second_group"}}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #4", fallback: true, outvar: "term_4", tip: "Enable termination on channel #4"}}, + {type: "Switch", args: {title: "Termination #5", fallback: true, outvar: "term_5", tip: "Enable termination on channel #5"}}, + {type: "Switch", args: {title: "Termination #6", fallback: true, outvar: "term_6", tip: "Enable termination on channel #6"}}, + {type: "Switch", args: {title: "Termination #7", fallback: true, outvar: "term_7", tip: "Enable termination on channel #7"}}, + ]}, + null + ] + } ], rules: { resources: { @@ -333,7 +357,31 @@ const shop_data = { ] ] }, - {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}} + { + "if": [ + {"!": {"var": "out_first_group"}}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #0", fallback: true, outvar: "term_0", tip: "Enable termination on channel #0"}}, + {type: "Switch", args: {title: "Termination #1", fallback: true, outvar: "term_1", tip: "Enable termination on channel #1"}}, + {type: "Switch", args: {title: "Termination #2", fallback: true, outvar: "term_2", tip: "Enable termination on channel #2"}}, + {type: "Switch", args: {title: "Termination #3", fallback: true, outvar: "term_3", tip: "Enable termination on channel #3"}}, + ]}, + null + ] + }, + {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}}, + { + "if": [ + {"!": {"var": "out_second_group"}}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #4", fallback: true, outvar: "term_4", tip: "Enable termination on channel #4"}}, + {type: "Switch", args: {title: "Termination #5", fallback: true, outvar: "term_5", tip: "Enable termination on channel #5"}}, + {type: "Switch", args: {title: "Termination #6", fallback: true, outvar: "term_6", tip: "Enable termination on channel #6"}}, + {type: "Switch", args: {title: "Termination #7", fallback: true, outvar: "term_7", tip: "Enable termination on channel #7"}}, + ]}, + null + ] + } ], size: 'small', type: null, @@ -380,9 +428,57 @@ const shop_data = { ] ] }, + { + "if": [ + {"!": {"var": "out_first_group"}}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #0", fallback: true, outvar: "term_0", tip: "Enable termination on channel #0"}}, + {type: "Switch", args: {title: "Termination #1", fallback: true, outvar: "term_1", tip: "Enable termination on channel #1"}}, + {type: "Switch", args: {title: "Termination #2", fallback: true, outvar: "term_2", tip: "Enable termination on channel #2"}}, + {type: "Switch", args: {title: "Termination #3", fallback: true, outvar: "term_3", tip: "Enable termination on channel #3"}}, + ]}, + null + ] + }, {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}}, + { + "if": [ + {"!": {"var": "out_second_group"}}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #4", fallback: true, outvar: "term_4", tip: "Enable termination on channel #4"}}, + {type: "Switch", args: {title: "Termination #5", fallback: true, outvar: "term_5", tip: "Enable termination on channel #5"}}, + {type: "Switch", args: {title: "Termination #6", fallback: true, outvar: "term_6", tip: "Enable termination on channel #6"}}, + {type: "Switch", args: {title: "Termination #7", fallback: true, outvar: "term_7", tip: "Enable termination on channel #7"}}, + ]}, + null + ] + }, {type: "Switch", args: {title: "Output third group", outvar: "out_third_group", fallback: true, tip: "Switch connectors 8-11 to output"}}, - {type: "Switch", args: {title: "Output fourth group", outvar: "out_fourth_group", fallback: true, tip: "Switch connectors 12-15 to output"}} + { + "if": [ + {"!": {"var": "out_third_group"}}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #8", fallback: true, outvar: "term_8", tip: "Enable termination on channel #8"}}, + {type: "Switch", args: {title: "Termination #9", fallback: true, outvar: "term_9", tip: "Enable termination on channel #9"}}, + {type: "Switch", args: {title: "Termination #10", fallback: true, outvar: "term_10", tip: "Enable termination on channel #10"}}, + {type: "Switch", args: {title: "Termination #11", fallback: true, outvar: "term_11", tip: "Enable termination on channel #11"}}, + ]}, + null + ] + }, + {type: "Switch", args: {title: "Output fourth group", outvar: "out_fourth_group", fallback: true, tip: "Switch connectors 12-15 to output"}}, + { + "if": [ + {"!": {"var": "out_fourth_group"}}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #12", fallback: true, outvar: "term_12", tip: "Enable termination on channel #12"}}, + {type: "Switch", args: {title: "Termination #13", fallback: true, outvar: "term_13", tip: "Enable termination on channel #13"}}, + {type: "Switch", args: {title: "Termination #14", fallback: true, outvar: "term_14", tip: "Enable termination on channel #14"}}, + {type: "Switch", args: {title: "Termination #15", fallback: true, outvar: "term_15", tip: "Enable termination on channel #15"}}, + ]}, + null + ] + } ], size: 'small', type: null, -- 2.42.0 From dfbf9cbfe79a8e60e519148286bfd5c4092a5081 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 12 Sep 2023 17:38:58 +0800 Subject: [PATCH 21/42] Fix scroll issue and found another bug Signed-off-by: Egor Savkin --- static/js/shop.jsx | 30 +++++++++++++++++++++++++----- static/js/shop_components.jsx | 16 ++++++++++++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 12adf3f..dc95982 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -708,18 +708,23 @@ class ProductCartItem extends React.PureComponent { big={data.size === "big"} target={{ construct: ((outvar, value) => { - //console.log("construct", outvar, value, options_data); + console.log("construct", outvar, value, options_data); options_data[outvar] = value; this.setState(options_data); }), update: ((outvar, value) => { - //console.log("update", outvar, value, options_data); + console.log("update", outvar, value, options_data); if (outvar in options_data) options_data[outvar] = value; this.setState(options_data); }), unmount: ((outvar) => { - //console.log("delete", outvar); - delete options_data[outvar]; + console.log("delete", outvar, this.state.alive); + //let opt_data = this.state; + //delete opt_data[outvar]; + //this.setState(opt_data); + // TODO this needs to be stopped when the whole card getting unmounted + if (this.state.alive) + delete options_data[outvar]; }) }} />) : null) } @@ -1720,8 +1725,12 @@ class Shop extends React.PureComponent { } handleDeleteItem(index) { - const cloned = Array.from(this.state.columns.cart.items); + console.log(this.state.columns.cart.items) + let cloned = Array.from(this.state.columns.cart.items); + let cloned_data = Array.from(this.state.columns.cart.itemsData); cloned.splice(index, 1); + cloned_data.splice(index, 1); + this.setState({ ...this.state, columns: { @@ -1729,6 +1738,7 @@ class Shop extends React.PureComponent { cart: { ...this.state.columns.cart, items: cloned, + itemsData: cloned_data, }, }, }); @@ -1742,6 +1752,7 @@ class Shop extends React.PureComponent { cart: { ...this.state.columns.cart, items: [], + itemsData: [] }, }, }); @@ -1976,6 +1987,10 @@ class Shop extends React.PureComponent { this.state.columns[source.droppableId].items, source.index, ), + itemsData: remove( + this.state.columns[source.droppableId].itemsData, + source.index, + ) }, }, }); @@ -2021,6 +2036,11 @@ class Shop extends React.PureComponent { source.index, destination.index, ), + itemsData: reorder( + this.state.columns[destination.droppableId].itemsData, + source.index, + destination.index, + ), }, }, }); diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index b074edc..1657e89 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -376,18 +376,20 @@ export function OptionsSummaryPopup({id, data}) { const [size, setSize] = useState({w: 0, h: 0}); const close = () => { setShow(false); - document.removeEventListener("scroll", reposition, true); + document.removeEventListener("scroll", handleScroll, true); } const ref = useClickAway(close); const reposition = () => { - console.trace("reposition") let popup_button = document.getElementById(id + "img"); + if (!popup_button) { + document.removeEventListener("scroll", handleScroll, true); + return; + } let rect = popup_button.getBoundingClientRect() let pos_x = (rect.left + rect.right) / 2; let pos_y = (rect.top + rect.bottom) / 2; - console.trace("reposition", pos_x, pos_y) if (pos_x + size.w > window.innerWidth) { setPosition({x: pos_x - size.w - 20, y: pos_y - size.h / 2}); } else { @@ -395,6 +397,12 @@ export function OptionsSummaryPopup({id, data}) { } } + const handleScroll = (e) => { + if (e.target !== document.getElementById(id)) { + close(); + } + } + useEffect(() => { if (show) { let popup = document.getElementById(id); @@ -415,7 +423,7 @@ export function OptionsSummaryPopup({id, data}) { const handleClick = (event) => { setShow(!show); if (!show) { - document.addEventListener("scroll", reposition, true); + document.addEventListener("scroll", handleScroll, true); } }; -- 2.42.0 From 840b0223a7b1c59fc9ee04d31a5026366d320c08 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Thu, 14 Sep 2023 17:47:45 +0800 Subject: [PATCH 22/42] Still fixing the bug Signed-off-by: Egor Savkin --- static/js/shop.jsx | 15 ++++---- static/js/shop_components.jsx | 51 ++++++++++++++++++++-------- static/js/shop_data.js | 64 +++++++++++++++++------------------ 3 files changed, 77 insertions(+), 53 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index dc95982..b4e208e 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -6,7 +6,7 @@ import { createRoot } from "react-dom/client"; import PropTypes from "prop-types"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { v4 as uuidv4 } from 'uuid'; -import { OptionsDialogPopup, OptionsSummaryPopup, fill_ext_data } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; +import { OptionsDialogPopup, OptionsSummaryPopup, FilterOptions, fill_ext_data } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; const data = window.shop_data; const itemsUnfoldedList = Array.from(data.columns.backlog.categories.map(groupId => groupId.itemIds).flat()); @@ -718,13 +718,13 @@ class ProductCartItem extends React.PureComponent { this.setState(options_data); }), unmount: ((outvar) => { - console.log("delete", outvar, this.state.alive); + console.log("delete", outvar); //let opt_data = this.state; //delete opt_data[outvar]; //this.setState(opt_data); // TODO this needs to be stopped when the whole card getting unmounted - if (this.state.alive) - delete options_data[outvar]; + //if (this.state.alive) + // delete options_data[outvar]; }) }} />) : null) } @@ -1442,6 +1442,9 @@ class OrderSumary extends React.PureComponent { } options = itemsData[index] && itemsData[index].options; options_data = itemsData[index] && itemsData[index].options_data; + let options_data_clone = Object.assign({}, options_data) + let display_options = FilterOptions(options, options_data_clone); // TODO fix faulty display + console.log(options, options_data, display_options) return ( ) : ( (options && options_data) ? - ( ) : null + ( ) : null )} {(!warning && !options) && ( @@ -1848,7 +1851,7 @@ class Shop extends React.PureComponent { const item_data = clonedCartData[i]; crate.items.push({ 'pn': item.name_number, - 'options': item_data.options_data ? item_data.options_data : null, + 'options': (item_data.options_data && item_data.options) ? FilterOptions(item_data.options, item_data.options_data) : null, // TODO }); } diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 1657e89..beaadd4 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -97,10 +97,6 @@ class Switch extends Component { this.props.target.construct(this.props.outvar, this.state.checked); } - componentWillUnmount() { - this.props.target.unmount(this.props.outvar); - } - handleClick() { // Update the state object with the new value for outvar let new_checked = !this.state.checked; @@ -165,10 +161,6 @@ class Line extends Component { this.props.target.construct(this.props.outvar, this.state.text); } - componentWillUnmount() { - this.props.target.unmount(this.props.outvar); - } - handleClick(element) { let text = element.target.value; this.setState({ @@ -225,10 +217,6 @@ class SwitchLine extends Component { this.props.target.construct(this.props.outvar, this.state); } - componentWillUnmount() { - this.props.target.unmount(this.props.outvar); - } - handleText(element) { let new_state = { ...this.state, @@ -329,7 +317,12 @@ export function ProcessOptions({options, data, target, id}) { } else if (options.type === "Group") { return (
- { ProcessOptions({options: jsonLogic.apply(options.items, data), data: data, target: target, id: id}) } + {ProcessOptions({ + options: jsonLogic.apply(options.items, data), + data: data, + target: target, + id: id + })}
); } else { return componentsList["Default"](options.type, id + "missing"); @@ -340,6 +333,34 @@ export function ProcessOptions({options, data, target, id}) { } } +export function FilterOptions(options, data) { + let options_t = trueTypeOf(options); + let target = {}; + console.log(options, data); + + if (options_t === "array") { + options.map((option_item, _) => { + Object.assign(target, FilterOptions(option_item, data)) + }); + } else if (options_t === "object") { + if ( + trueTypeOf(options.type) === "string" && + (trueTypeOf(options.args) === "object" || trueTypeOf(options.items) === "array") + ) { + if (options.type in componentsList) { + console.log(options.args.outvar, data[options.args.outvar], data); + target[options.args.outvar] = data[options.args.outvar]; + } else if (options.type === "Group") { + Object.assign(target, FilterOptions(jsonLogic.apply(options.items, data), data)) + } + } else { + Object.assign(target, FilterOptions(jsonLogic.apply(options, data), data)) + } + } + console.log(target) + return target +} + export function OptionsDialogPopup({options, data, target, id, big}) { const [show, setShow] = useState(false); const ref = useClickAway((e) => { @@ -465,8 +486,8 @@ export function OptionsSummaryPopup({id, data}) { export function fill_ext_data(data, index) { return { has_other_dio: data.filter((value, item_index) => index !== item_index && value.name.endsWith("-TTL")).length > 0, - has_dds: data.filter(((value, _) => value.name === "DDS" )).length > 0, - has_sampler: data.filter(((value, _) => value.name === "Sampler" )).length > 0 + has_dds: data.filter(((value, _) => value.name === "DDS")).length > 0, + has_sampler: data.filter(((value, _) => value.name === "Sampler")).length > 0 } } diff --git a/static/js/shop_data.js b/static/js/shop_data.js index eebe791..6ffe8b4 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -302,10 +302,10 @@ const shop_data = { "if": [ {"!": {"var": "out_first_group"}}, {type: "Group", items: [ - {type: "Switch", args: {title: "Termination #0", fallback: true, outvar: "term_0", tip: "Enable termination on channel #0"}}, - {type: "Switch", args: {title: "Termination #1", fallback: true, outvar: "term_1", tip: "Enable termination on channel #1"}}, - {type: "Switch", args: {title: "Termination #2", fallback: true, outvar: "term_2", tip: "Enable termination on channel #2"}}, - {type: "Switch", args: {title: "Termination #3", fallback: true, outvar: "term_3", tip: "Enable termination on channel #3"}}, + {type: "Switch", args: {title: "Termination #0", outvar: "term_0", tip: "Enable termination on channel #0"}}, + {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on channel #1"}}, + {type: "Switch", args: {title: "Termination #2", outvar: "term_2", tip: "Enable termination on channel #2"}}, + {type: "Switch", args: {title: "Termination #3", outvar: "term_3", tip: "Enable termination on channel #3"}}, ]}, null ] @@ -315,10 +315,10 @@ const shop_data = { "if": [ {"!": {"var": "out_second_group"}}, {type: "Group", items: [ - {type: "Switch", args: {title: "Termination #4", fallback: true, outvar: "term_4", tip: "Enable termination on channel #4"}}, - {type: "Switch", args: {title: "Termination #5", fallback: true, outvar: "term_5", tip: "Enable termination on channel #5"}}, - {type: "Switch", args: {title: "Termination #6", fallback: true, outvar: "term_6", tip: "Enable termination on channel #6"}}, - {type: "Switch", args: {title: "Termination #7", fallback: true, outvar: "term_7", tip: "Enable termination on channel #7"}}, + {type: "Switch", args: {title: "Termination #4", outvar: "term_4", tip: "Enable termination on channel #4"}}, + {type: "Switch", args: {title: "Termination #5", outvar: "term_5", tip: "Enable termination on channel #5"}}, + {type: "Switch", args: {title: "Termination #6", outvar: "term_6", tip: "Enable termination on channel #6"}}, + {type: "Switch", args: {title: "Termination #7", outvar: "term_7", tip: "Enable termination on channel #7"}}, ]}, null ] @@ -361,10 +361,10 @@ const shop_data = { "if": [ {"!": {"var": "out_first_group"}}, {type: "Group", items: [ - {type: "Switch", args: {title: "Termination #0", fallback: true, outvar: "term_0", tip: "Enable termination on channel #0"}}, - {type: "Switch", args: {title: "Termination #1", fallback: true, outvar: "term_1", tip: "Enable termination on channel #1"}}, - {type: "Switch", args: {title: "Termination #2", fallback: true, outvar: "term_2", tip: "Enable termination on channel #2"}}, - {type: "Switch", args: {title: "Termination #3", fallback: true, outvar: "term_3", tip: "Enable termination on channel #3"}}, + {type: "Switch", args: {title: "Termination #0", outvar: "term_0", tip: "Enable termination on channel #0"}}, + {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on channel #1"}}, + {type: "Switch", args: {title: "Termination #2", outvar: "term_2", tip: "Enable termination on channel #2"}}, + {type: "Switch", args: {title: "Termination #3", outvar: "term_3", tip: "Enable termination on channel #3"}}, ]}, null ] @@ -374,10 +374,10 @@ const shop_data = { "if": [ {"!": {"var": "out_second_group"}}, {type: "Group", items: [ - {type: "Switch", args: {title: "Termination #4", fallback: true, outvar: "term_4", tip: "Enable termination on channel #4"}}, - {type: "Switch", args: {title: "Termination #5", fallback: true, outvar: "term_5", tip: "Enable termination on channel #5"}}, - {type: "Switch", args: {title: "Termination #6", fallback: true, outvar: "term_6", tip: "Enable termination on channel #6"}}, - {type: "Switch", args: {title: "Termination #7", fallback: true, outvar: "term_7", tip: "Enable termination on channel #7"}}, + {type: "Switch", args: {title: "Termination #4", outvar: "term_4", tip: "Enable termination on channel #4"}}, + {type: "Switch", args: {title: "Termination #5", outvar: "term_5", tip: "Enable termination on channel #5"}}, + {type: "Switch", args: {title: "Termination #6", outvar: "term_6", tip: "Enable termination on channel #6"}}, + {type: "Switch", args: {title: "Termination #7", outvar: "term_7", tip: "Enable termination on channel #7"}}, ]}, null ] @@ -432,10 +432,10 @@ const shop_data = { "if": [ {"!": {"var": "out_first_group"}}, {type: "Group", items: [ - {type: "Switch", args: {title: "Termination #0", fallback: true, outvar: "term_0", tip: "Enable termination on channel #0"}}, - {type: "Switch", args: {title: "Termination #1", fallback: true, outvar: "term_1", tip: "Enable termination on channel #1"}}, - {type: "Switch", args: {title: "Termination #2", fallback: true, outvar: "term_2", tip: "Enable termination on channel #2"}}, - {type: "Switch", args: {title: "Termination #3", fallback: true, outvar: "term_3", tip: "Enable termination on channel #3"}}, + {type: "Switch", args: {title: "Termination #0", outvar: "term_0", tip: "Enable termination on channel #0"}}, + {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on channel #1"}}, + {type: "Switch", args: {title: "Termination #2", outvar: "term_2", tip: "Enable termination on channel #2"}}, + {type: "Switch", args: {title: "Termination #3", outvar: "term_3", tip: "Enable termination on channel #3"}}, ]}, null ] @@ -445,10 +445,10 @@ const shop_data = { "if": [ {"!": {"var": "out_second_group"}}, {type: "Group", items: [ - {type: "Switch", args: {title: "Termination #4", fallback: true, outvar: "term_4", tip: "Enable termination on channel #4"}}, - {type: "Switch", args: {title: "Termination #5", fallback: true, outvar: "term_5", tip: "Enable termination on channel #5"}}, - {type: "Switch", args: {title: "Termination #6", fallback: true, outvar: "term_6", tip: "Enable termination on channel #6"}}, - {type: "Switch", args: {title: "Termination #7", fallback: true, outvar: "term_7", tip: "Enable termination on channel #7"}}, + {type: "Switch", args: {title: "Termination #4", outvar: "term_4", tip: "Enable termination on channel #4"}}, + {type: "Switch", args: {title: "Termination #5", outvar: "term_5", tip: "Enable termination on channel #5"}}, + {type: "Switch", args: {title: "Termination #6", outvar: "term_6", tip: "Enable termination on channel #6"}}, + {type: "Switch", args: {title: "Termination #7", outvar: "term_7", tip: "Enable termination on channel #7"}}, ]}, null ] @@ -458,10 +458,10 @@ const shop_data = { "if": [ {"!": {"var": "out_third_group"}}, {type: "Group", items: [ - {type: "Switch", args: {title: "Termination #8", fallback: true, outvar: "term_8", tip: "Enable termination on channel #8"}}, - {type: "Switch", args: {title: "Termination #9", fallback: true, outvar: "term_9", tip: "Enable termination on channel #9"}}, - {type: "Switch", args: {title: "Termination #10", fallback: true, outvar: "term_10", tip: "Enable termination on channel #10"}}, - {type: "Switch", args: {title: "Termination #11", fallback: true, outvar: "term_11", tip: "Enable termination on channel #11"}}, + {type: "Switch", args: {title: "Termination #8", outvar: "term_8", tip: "Enable termination on channel #8"}}, + {type: "Switch", args: {title: "Termination #9", outvar: "term_9", tip: "Enable termination on channel #9"}}, + {type: "Switch", args: {title: "Termination #10", outvar: "term_10", tip: "Enable termination on channel #10"}}, + {type: "Switch", args: {title: "Termination #11", outvar: "term_11", tip: "Enable termination on channel #11"}}, ]}, null ] @@ -471,10 +471,10 @@ const shop_data = { "if": [ {"!": {"var": "out_fourth_group"}}, {type: "Group", items: [ - {type: "Switch", args: {title: "Termination #12", fallback: true, outvar: "term_12", tip: "Enable termination on channel #12"}}, - {type: "Switch", args: {title: "Termination #13", fallback: true, outvar: "term_13", tip: "Enable termination on channel #13"}}, - {type: "Switch", args: {title: "Termination #14", fallback: true, outvar: "term_14", tip: "Enable termination on channel #14"}}, - {type: "Switch", args: {title: "Termination #15", fallback: true, outvar: "term_15", tip: "Enable termination on channel #15"}}, + {type: "Switch", args: {title: "Termination #12", outvar: "term_12", tip: "Enable termination on channel #12"}}, + {type: "Switch", args: {title: "Termination #13", outvar: "term_13", tip: "Enable termination on channel #13"}}, + {type: "Switch", args: {title: "Termination #14", outvar: "term_14", tip: "Enable termination on channel #14"}}, + {type: "Switch", args: {title: "Termination #15", outvar: "term_15", tip: "Enable termination on channel #15"}}, ]}, null ] -- 2.42.0 From 79e4253e0f8bea006c394b1802d347e0643ad51a Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Mon, 18 Sep 2023 11:49:56 +0800 Subject: [PATCH 23/42] Fixed initial display of empty options in the options summary Signed-off-by: Egor Savkin --- static/js/shop.jsx | 23 +++++------------------ static/js/shop_components.jsx | 8 +++----- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index b4e208e..013451a 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -708,23 +708,14 @@ class ProductCartItem extends React.PureComponent { big={data.size === "big"} target={{ construct: ((outvar, value) => { - console.log("construct", outvar, value, options_data); + // console.log("construct", outvar, value, options_data); options_data[outvar] = value; this.setState(options_data); }), update: ((outvar, value) => { - console.log("update", outvar, value, options_data); + // console.log("update", outvar, value, options_data); if (outvar in options_data) options_data[outvar] = value; this.setState(options_data); - }), - unmount: ((outvar) => { - console.log("delete", outvar); - //let opt_data = this.state; - //delete opt_data[outvar]; - //this.setState(opt_data); - // TODO this needs to be stopped when the whole card getting unmounted - //if (this.state.alive) - // delete options_data[outvar]; }) }} />) : null) } @@ -1442,9 +1433,6 @@ class OrderSumary extends React.PureComponent { } options = itemsData[index] && itemsData[index].options; options_data = itemsData[index] && itemsData[index].options_data; - let options_data_clone = Object.assign({}, options_data) - let display_options = FilterOptions(options, options_data_clone); // TODO fix faulty display - console.log(options, options_data, display_options) return ( ) : ( (options && options_data) ? - ( ) : null + ( ) : null )} {(!warning && !options) && ( @@ -1728,7 +1716,6 @@ class Shop extends React.PureComponent { } handleDeleteItem(index) { - console.log(this.state.columns.cart.items) let cloned = Array.from(this.state.columns.cart.items); let cloned_data = Array.from(this.state.columns.cart.itemsData); cloned.splice(index, 1); @@ -1851,7 +1838,7 @@ class Shop extends React.PureComponent { const item_data = clonedCartData[i]; crate.items.push({ 'pn': item.name_number, - 'options': (item_data.options_data && item_data.options) ? FilterOptions(item_data.options, item_data.options_data) : null, // TODO + 'options': (item_data.options_data && item_data.options) ? FilterOptions(item_data.options, item_data.options_data) : null, }); } @@ -1936,7 +1923,7 @@ class Shop extends React.PureComponent { const item_data = clonedCartData[i]; crate.items.push({ 'pn': item.name_number, - 'options': item_data.options_data ? item_data.options_data : null, + 'options': (item_data.options_data && item_data.options) ? FilterOptions(item_data.options, item_data.options_data) : null, }); } diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index beaadd4..18b48ce 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -336,7 +336,6 @@ export function ProcessOptions({options, data, target, id}) { export function FilterOptions(options, data) { let options_t = trueTypeOf(options); let target = {}; - console.log(options, data); if (options_t === "array") { options.map((option_item, _) => { @@ -348,7 +347,6 @@ export function FilterOptions(options, data) { (trueTypeOf(options.args) === "object" || trueTypeOf(options.items) === "array") ) { if (options.type in componentsList) { - console.log(options.args.outvar, data[options.args.outvar], data); target[options.args.outvar] = data[options.args.outvar]; } else if (options.type === "Group") { Object.assign(target, FilterOptions(jsonLogic.apply(options.items, data), data)) @@ -357,7 +355,6 @@ export function FilterOptions(options, data) { Object.assign(target, FilterOptions(jsonLogic.apply(options, data), data)) } } - console.log(target) return target } @@ -391,10 +388,11 @@ export function OptionsDialogPopup({options, data, target, id, big}) { ); } -export function OptionsSummaryPopup({id, data}) { +export function OptionsSummaryPopup({id, options, data}) { const [show, setShow] = useState(false); const [position, setPosition] = useState({x: 0, y: 0}); const [size, setSize] = useState({w: 0, h: 0}); + let display_options = FilterOptions(options, data); const close = () => { setShow(false); document.removeEventListener("scroll", handleScroll, true); @@ -472,7 +470,7 @@ export function OptionsSummaryPopup({id, data}) { className="overlayVariant card border rounded" id={id}>
- {Array.from(Object.entries(data) + {Array.from(Object.entries(display_options) .filter(([key, value], _) => key !== "ext_data") .map(([key, value], _) => { return (

{key}: {stringify(value)}

); -- 2.42.0 From ce31357802d4201921b3bca8942f7b1367f5c2e3 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 19 Sep 2023 10:59:34 +0800 Subject: [PATCH 24/42] Integrate clock/slots configuration into the calculator Also adjust sizes Signed-off-by: Egor Savkin --- sass/css/_shop.scss | 12 +++++---- static/js/shop.jsx | 47 +++++++++++++++++++++++------------ static/js/shop_components.jsx | 6 +---- static/js/shop_data.js | 3 ++- 4 files changed, 41 insertions(+), 27 deletions(-) diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index 9a02dea..3de09b5 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -268,7 +268,8 @@ button { .overlayVariant { min-width: 100px; - height: 150px; + max-height: 150px; + min-height: 50px; overflow-y: scroll; position: absolute; display: flex; @@ -488,8 +489,8 @@ button { .overlayVariant { top: 24px; - width: 132px; - min-height: 70px; + width: 140px; + min-height: 40px; max-height: 320px; overflow-y: scroll; position: absolute; @@ -500,6 +501,7 @@ button { color: black; flex-direction: column; cursor: pointer; + padding: 0.2rem 0; p { font-size: .65rem; @@ -535,10 +537,10 @@ button { } .overlay-smallcard { - right: -34.5px; + right: -38.5px; // (card width (63) - overlay width (140)) / 2 } .overlay-bigcard { - right: -3px; + right: -7px; // (card width (126) - overlay width (140)) / 2 } .hovered { diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 013451a..bf60b5b 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -6,7 +6,7 @@ import { createRoot } from "react-dom/client"; import PropTypes from "prop-types"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { v4 as uuidv4 } from 'uuid'; -import { OptionsDialogPopup, OptionsSummaryPopup, FilterOptions, fill_ext_data } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; +import { OptionsDialogPopup, OptionsSummaryPopup, FilterOptions, FillExtData } from "./shop_components.jsx";import { OverlayTrigger } from "react-bootstrap"; const data = window.shop_data; const itemsUnfoldedList = Array.from(data.columns.backlog.categories.map(groupId => groupId.itemIds).flat()); @@ -866,7 +866,7 @@ class Cart extends React.PureComponent { const products = data.items.map((item, index) => { let itemData; - let ext_data = fill_ext_data(data.itemsData, index); + let ext_data = FillExtData(data.itemsData, index); if (data.itemsData && index in data.itemsData) { itemData = data.itemsData[index]; } @@ -1846,7 +1846,7 @@ class Shop extends React.PureComponent { isProcessing: false, shouldShowRFQFeedback: true, RFQBodyType: 'show', - RFQBodyOrder: JSON.stringify(crate), + RFQBodyOrder: JSON.stringify(crate, null, 2), }); } @@ -1862,8 +1862,6 @@ class Shop extends React.PureComponent { if (!customconf) {return; } const items = this.props.data.items; - console.trace(customconf); - const self = this; let new_items = []; let new_items_data = []; @@ -1889,7 +1887,7 @@ class Shop extends React.PureComponent { id: uuidv4(), options_data: item.options ? item.options : null, })); - new_items_data.push({options_data: item.options? item.options : null}); + new_items_data.push({options_data: item.options ? item.options : null}); } }); @@ -2067,6 +2065,13 @@ class Shop extends React.PureComponent { const itemsData = []; const rules = {}; + itemsCloned.forEach((elem, idx) => { + if (!(idx in itemsData)) itemsData[idx] = elem; + if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) { + itemsCloned[idx].options_data = this.state.columns.cart.itemsData[idx].options_data; + } + }); + // check number of slot in crate const nbrOccupied = nbrOccupiedSlotsInCrate(newItems); @@ -2116,14 +2121,31 @@ class Shop extends React.PureComponent { } } + const process_slots = (item) => { + if (!item.options_data + || item.options_data.ext_pwr === false + || item.options_data.mono_eem === false + ) + return item.slotOccupied; + else if (item.options_data.ext_pwr === true) + return 0; + else if (item.options_data.mono_eem === true || item.options_data.n_eem === "1 EEM") + return 1; + else if (item.options_data.n_eem === "3 EEM") + return 3; + + return item.slotOccupied; + } + nbUsedSlot = slots .filter(item => item.type !== 'idc-bnc') .reduce((prev, next) => { - return prev + next.slotOccupied; + return prev + process_slots(next); }, 0); + nbrCurrentClock = slots .reduce((prev, next) => { - return next.type === 'clocker' ? prev + next.clockOccupied : prev; + return next.type === 'clocker' ? prev + ((next.options_data && next.options_data.ext_clk === true) ? 0 : next.clockOccupied) : prev; }, 0); if (idx in itemsData) { @@ -2199,7 +2221,7 @@ class Shop extends React.PureComponent { } nbrCurrentClock = slots.reduce((prev, next) => { - return prev + next.clockOccupied; + return prev + ((next.options_data && next.options_data.ext_clk && next.options_data.ext_clk.checked) ? 0 : next.clockOccupied); }, 0); if (idx in itemsData) { @@ -2340,13 +2362,6 @@ class Shop extends React.PureComponent { } } - itemsCloned.forEach((elem, idx) => { - if (!(idx in itemsData)) itemsData[idx] = elem; - if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) { - itemsData[idx].options_data = this.state.columns.cart.itemsData[idx].options_data; - } - }); - // update state with rules this.setState({ ...this.state, diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 18b48ce..8826632 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -23,10 +23,6 @@ class Radio extends Component { this.props.target.construct(this.props.outvar, this.state.variant); } - componentWillUnmount() { - this.props.target.unmount(this.props.outvar); - } - handleClick(variant) { // Update the state object with the new value for outvar this.setState({ @@ -481,7 +477,7 @@ export function OptionsSummaryPopup({id, options, data}) { ); } -export function fill_ext_data(data, index) { +export function FillExtData(data, index) { return { has_other_dio: data.filter((value, item_index) => index !== item_index && value.name.endsWith("-TTL")).length > 0, has_dds: data.filter(((value, _) => value.name === "DDS")).length > 0, diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 6ffe8b4..900a143 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -552,6 +552,7 @@ const shop_data = { datasheet_name: '4410/4412 Urukul datasheet', options: [ {type: "Switch", args: {title: "AD9912", outvar: "ad9912", tip: "AD9912 chip instead of AD9910"}}, + {type: "Switch", args: {title: "Use 1 EEM", outvar: "mono_eem", tip: "Use one EEM port setup. RF switch and synchronization will be unavailable."}}, { "if": [ {"var": "ad9912"}, @@ -559,7 +560,7 @@ const shop_data = { {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, ], [ - {type: "Switch", args: {title: "Synchronization", outvar: "sync"}}, + {type: "Switch", args: {title: "Synchronization", outvar: "sync", tip: "Synchronize phases across Urukuls"}}, { "if": [ {"var": "sync"}, -- 2.42.0 From 5559a04403987aaefb4c19d08a975913dd4b1606 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 19 Sep 2023 11:35:22 +0800 Subject: [PATCH 25/42] Remove redundant notifications about connectors and AD9910 Signed-off-by: Egor Savkin --- static/js/shop.jsx | 9 --------- static/js/shop_data.js | 31 ++++--------------------------- 2 files changed, 4 insertions(+), 36 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index bf60b5b..5a143d8 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -2243,15 +2243,6 @@ class Shop extends React.PureComponent { } - // check for number of recommended EEM connectors - ['novo', 'urukul', 'koster'].map(_type => { - if (itemsCloned.find(elem => elem.type === _type)) { - rules[this.state.items[_type].rules.connectors.type] = {...this.state.items[_type].rules.connectors}; - } - return _type; - }); - - if (itemsCloned.find(elem => elem.type === 'urukul')) { if (this.state.items['urukul'].rules.info) { rules[this.state.items['urukul'].rules.info.type] = {...this.state.items['urukul'].rules.info}; diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 900a143..c14a4f9 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -555,7 +555,7 @@ const shop_data = { {type: "Switch", args: {title: "Use 1 EEM", outvar: "mono_eem", tip: "Use one EEM port setup. RF switch and synchronization will be unavailable."}}, { "if": [ - {"var": "ad9912"}, + {"or": [{"var": "ad9912"}, {"var": "mono_eem"}]}, [ {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, ], @@ -590,18 +590,6 @@ const shop_data = { slotOccupied: 2, clockOccupied: 1, rules: { - connectors: { - type: 'urukul', - icon: '/shop/icon-reminder.svg', - name: 'Urukul', - message: 'This configuration uses 2 EEM connectors as it is recommended. If you prefer to use 1 EEM connector, please inform us by leaving an additional note.', - }, - info: { - type: 'urukul-info', - icon: '/shop/icon-reminder.svg', - name: 'Urukul', - message: 'The default chip is AD9910, which supports more features. If you need the higher frequency resolution of the AD9912, leave us a note.', - }, resources: { type: 'urukul', icon: '/shop/icon-warning.svg', @@ -635,7 +623,7 @@ const shop_data = { nbrSlotMin: 0, nbrSlotMax: 0, nbrClockMax: 0, - slotOccupied: 2, + slotOccupied: 1, clockOccupied: 1, rules: { resources: { @@ -883,9 +871,10 @@ const shop_data = { 'Supports SU-Servo laser intensity stabilization servo in conjunction with Urukul.' ], options: [ + {type: "Switch", args: {title: "1 EEM mode", outvar: "mono_eem"}}, { "if": [ - {"var": "ext_data.has_dds"}, + {"and": [{"var": "ext_data.has_dds"}, {"!": {"var": "mono_eem"}}]}, {type: "Switch", args: {title: "SUServo mode", outvar: "suservo"}}, null ] @@ -900,12 +889,6 @@ const shop_data = { slotOccupied: 2, clockOccupied: 0, rules: { - connectors: { - type: 'novo', - icon: '/shop/icon-reminder.svg', - name: 'Sampler', - message: 'This configuration uses 2 EEM connectors as it is recommended. If you prefer to use 1 EEM connector, please inform us by leaving an additional note.', - }, resources: { type: 'novo', icon: '/shop/icon-warning.svg', @@ -940,12 +923,6 @@ const shop_data = { slotOccupied: 2, clockOccupied: 0, rules: { - connectors: { - type: 'koster', - icon: '/shop/icon-reminder.svg', - name: 'Grabber', - message: 'This configuration uses 2 EEM connectors. If you prefer to use 1 or 3 EEM connectors, please inform us by leaving an additional note.', - }, resources: { type: 'koster', icon: '/shop/icon-warning.svg', -- 2.42.0 From 58bc01cf06220c759d3811fe5fefa33e4ba4b19e Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 19 Sep 2023 14:31:14 +0800 Subject: [PATCH 26/42] Small duplication removal Signed-off-by: Egor Savkin --- static/js/shop_components.jsx | 94 +++++++++++------------------------ 1 file changed, 29 insertions(+), 65 deletions(-) diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 8826632..c5142ea 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -7,9 +7,22 @@ import {useClickAway} from "@uidotdev/usehooks"; import {OverlayTrigger, Tooltip} from "react-bootstrap"; // https://stackoverflow.com/a/70511311 -const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); +const true_type_of = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); +function Tip({id, tip}) { + return ( + {tip}} + > + + + ); +} + class Radio extends Component { constructor(props) { super(props); @@ -37,22 +50,10 @@ class Radio extends Component { return (
- {this.props.icon ? : null} + {this.props.icon && } {this.props.title}
- { - this.props.tip ? - ( - {this.props.tip} - - }> - - ) - : - null - } + {this.props.tip && } {this.props.variants.map((variant, _) => (
- { - this.props.tip ? - ( - {this.props.tip} - - }> - - ) - : - null - } + {this.props.tip && }
); @@ -169,24 +158,11 @@ class Line extends Component { let key = this.props.id + this.props.outvar; return (
- - { - this.props.tip ? - ( - {this.props.tip} - - }> - - ) - : - null - } + {this.props.tip && }
@@ -247,22 +223,10 @@ class SwitchLine extends Component { onChange={this.handleCheck} /> - { - this.props.tip ? - ( - {this.props.tip} - - }> - - ) - : - null - } + {this.props.tip && }
@@ -292,7 +256,7 @@ const componentsList = { export function ProcessOptions({options, data, target, id}) { - let options_t = trueTypeOf(options); + let options_t = true_type_of(options); if (options_t === "array") { return Array.from( @@ -305,8 +269,8 @@ export function ProcessOptions({options, data, target, id}) { ); } else if (options_t === "object") { if ( - trueTypeOf(options.type) === "string" && - (trueTypeOf(options.args) === "object" || trueTypeOf(options.items) === "array") + true_type_of(options.type) === "string" && + (true_type_of(options.args) === "object" || true_type_of(options.items) === "array") ) { if (options.type in componentsList) { return componentsList[options.type](target, id + options.type, data, options.args); @@ -330,7 +294,7 @@ export function ProcessOptions({options, data, target, id}) { } export function FilterOptions(options, data) { - let options_t = trueTypeOf(options); + let options_t = true_type_of(options); let target = {}; if (options_t === "array") { @@ -339,8 +303,8 @@ export function FilterOptions(options, data) { }); } else if (options_t === "object") { if ( - trueTypeOf(options.type) === "string" && - (trueTypeOf(options.args) === "object" || trueTypeOf(options.items) === "array") + true_type_of(options.type) === "string" && + (true_type_of(options.args) === "object" || true_type_of(options.items) === "array") ) { if (options.type in componentsList) { target[options.args.outvar] = data[options.args.outvar]; @@ -443,7 +407,7 @@ export function OptionsSummaryPopup({id, options, data}) { }; const stringify = (value) => { - let value_type = trueTypeOf(value); + let value_type = true_type_of(value); if (value_type === "string") { return value; } else if (value_type === "object") { -- 2.42.0 From 1a0b613044061d9c3592a8af2c617bcdbd43bea9 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Mon, 25 Sep 2023 14:16:49 +0800 Subject: [PATCH 27/42] Fix not-disappearing warnings and clocker clock slots Signed-off-by: Egor Savkin --- static/js/shop.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 5a143d8..3e00905 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -2070,6 +2070,7 @@ class Shop extends React.PureComponent { if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) { itemsCloned[idx].options_data = this.state.columns.cart.itemsData[idx].options_data; } + itemsData[idx].warnings = {}; }); @@ -2225,7 +2226,7 @@ class Shop extends React.PureComponent { }, 0); if (idx in itemsData) { - if (itemsData[idx].nbrCurrentClock) { + if (itemsData[idx].nbrCurrentClock && itemsData[idx].type !== "clocker") { itemsData[idx].nbrCurrentClock += nbrCurrentClock; } else { itemsData[idx].nbrCurrentClock = nbrCurrentClock; -- 2.42.0 From acdaeda699f7b38c99150c6c75fac076be7946ee Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Mon, 25 Sep 2023 14:51:58 +0800 Subject: [PATCH 28/42] Fix cards state being not updated on touchables Signed-off-by: Egor Savkin --- static/js/shop.jsx | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 3e00905..27c3a08 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -542,6 +542,7 @@ class ProductCartItem extends React.PureComponent { onToggleOverlayRemove: PropTypes.func, onClickRemoveItem: PropTypes.func, onClickItem: PropTypes.func, + onCardUpdate: PropTypes.func, }; } @@ -593,6 +594,7 @@ class ProductCartItem extends React.PureComponent { data, index, ext_data, + onCardUpdate, } = this.props; let warning, options, options_data; @@ -710,12 +712,12 @@ class ProductCartItem extends React.PureComponent { construct: ((outvar, value) => { // console.log("construct", outvar, value, options_data); options_data[outvar] = value; - this.setState(options_data); + onCardUpdate(); }), update: ((outvar, value) => { // console.log("update", outvar, value, options_data); if (outvar in options_data) options_data[outvar] = value; - this.setState(options_data); + onCardUpdate(); }) }} />) : null) } @@ -848,6 +850,7 @@ class Cart extends React.PureComponent { data: PropTypes.object.isRequired, onToggleOverlayRemove: PropTypes.func, onClickRemoveItem: PropTypes.func, + onCardUpdate: PropTypes.func, onClickItem: PropTypes.func, }; } @@ -862,6 +865,7 @@ class Cart extends React.PureComponent { onToggleOverlayRemove, onClickRemoveItem, onClickItem, + onCardUpdate, } = this.props; const products = data.items.map((item, index) => { @@ -883,6 +887,7 @@ class Cart extends React.PureComponent { ext_data={ext_data} onToggleOverlayRemove={onToggleOverlayRemove} onClickRemoveItem={onClickRemoveItem} + onCardUpdate={onCardUpdate} onClickItem={onClickItem} model={item}> @@ -1654,6 +1659,7 @@ class Shop extends React.PureComponent { this.handleClickShowOrder = this.handleClickShowOrder.bind(this); this.handleClickOpenImport = this.handleClickOpenImport.bind(this); this.handleLoadCustomConf = this.handleLoadCustomConf.bind(this); + this.handleCardsUpdated = this.handleCardsUpdated.bind(this); this.timer = null; this.timer_remove = null; @@ -1691,9 +1697,7 @@ class Shop extends React.PureComponent { (prevState.columns.cart.items !== this.state.columns.cart.items) || (prevState.currentMode !== this.state.currentMode) ) { - this.checkAlerts( - prevState.columns.cart.items, - this.state.columns.cart.items); + this.checkAlerts(this.state.columns.cart.items); } if (this.state.newCardJustAdded) { @@ -1709,6 +1713,10 @@ class Shop extends React.PureComponent { clearTimeout(this.timer); } + handleCardsUpdated() { + this.checkAlerts(this.state.columns.cart.items); + } + handleCrateModeChange(mode) { this.setState({ currentMode: mode, @@ -2052,7 +2060,7 @@ class Shop extends React.PureComponent { }); } - checkAlerts(prevItems, newItems) { + checkAlerts(newItems) { console.log('--- START CHECKING CRATE WARNING ---'); const { @@ -2444,6 +2452,8 @@ class Shop extends React.PureComponent { onToggleOverlayRemove={this.handleToggleOverlayRemove} onClickRemoveItem={this.handleDeleteItem} onClickItem={this.handleShowOverlayRemove}> + onClickRemoveItem={this.handleDeleteItem} + onCardUpdate={this.handleCardsUpdated}> } rules={Object.values(rules).filter(rule => rule)}> -- 2.42.0 From bd15b8d19d81f4b5574236d0c2895f30b00c65ea Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Mon, 25 Sep 2023 16:46:54 +0800 Subject: [PATCH 29/42] Slightly promote new functionality and consider mono_eem modes on sampler/urukul for suservo Signed-off-by: Egor Savkin --- static/js/shop.jsx | 3 +-- static/js/shop_components.jsx | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 27c3a08..188f50c 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -712,7 +712,6 @@ class ProductCartItem extends React.PureComponent { construct: ((outvar, value) => { // console.log("construct", outvar, value, options_data); options_data[outvar] = value; - onCardUpdate(); }), update: ((outvar, value) => { // console.log("update", outvar, value, options_data); @@ -2433,7 +2432,7 @@ class Shop extends React.PureComponent { isMobile={isMobile} title="Order hardware" description=" - Drag and drop the cards you want into the crate below to see how the combination would look like. If you have any issues with this ordering system, or if you need other configurations, email us directly anytime at sales@m-****.hk. The price is estimated and must be confirmed by a quote." + Drag and drop the cards you want into the crate below to see how the combination would look like. Setup card's configuration by tapping at the top of the card. If you have any issues with this ordering system, or if you need other configurations, email us directly anytime at sales@m-****.hk. The price is estimated and must be confirmed by a quote." crateMode={ index !== item_index && value.name.endsWith("-TTL")).length > 0, - has_dds: data.filter(((value, _) => value.name === "DDS")).length > 0, - has_sampler: data.filter(((value, _) => value.name === "Sampler")).length > 0 + has_dds: data.filter(((value, _) => value.name === "DDS" && (!value.options_data || !value.options_data.mono_eem))).length > 0, + has_sampler: data.filter(((value, _) => value.name === "Sampler" && (!value.options_data || !value.options_data.mono_eem))).length > 0 } } -- 2.42.0 From cd780b83e44ab1c6e026115c2a364092ec64f859 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Mon, 25 Sep 2023 17:49:01 +0800 Subject: [PATCH 30/42] Change ttl groups to banks and remove green leaf Signed-off-by: Egor Savkin --- static/images/shop/icon-leaf.svg | 1 - static/js/shop_data.js | 42 ++++++++++++++++---------------- 2 files changed, 21 insertions(+), 22 deletions(-) delete mode 100644 static/images/shop/icon-leaf.svg diff --git a/static/images/shop/icon-leaf.svg b/static/images/shop/icon-leaf.svg deleted file mode 100644 index f11ca49..0000000 --- a/static/images/shop/icon-leaf.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/static/js/shop_data.js b/static/js/shop_data.js index c14a4f9..8a9ba72 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -79,7 +79,7 @@ const shop_data = { {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24", tip: "Set up IPv4 address used by core device"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}, tip: "Use external clock reference: 10, 80 (beta), 100 or 125 MHz. Other variants may be provided if needed."}}, - {type: "Switch", args: {title: "Email device_db", outvar: "email_ddb", icon: "/shop/icon-leaf.svg", tip: "Send the device_db.py file by email instead of USB-drive"}}, + {type: "Switch", args: {title: "Opt out from promotional USB-stick", outvar: "usb_opt_out", tip: "Do not ship a promotional USB-stick"}}, ], [ {type: "Switch", args: {title: "Optic fiber", outvar: "optics", tip: "Use optic fiber instead of direct attach copper cable"}} @@ -163,7 +163,7 @@ const shop_data = { {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24", tip: "Set up IPv4 address used by core device"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}, tip: "Use external clock reference: 10, 80 (beta), 100 or 125 MHz. Other variants may be provided if needed."}}, - {type: "Switch", args: {title: "Email device_db", outvar: "email_ddb", icon: "/shop/icon-leaf.svg", tip: "Send the device_db.py file by email instead of USB-drive"}}, + {type: "Switch", args: {title: "Opt out from promotional USB-stick", outvar: "usb_opt_out", tip: "Do not ship a promotional USB-stick"}}, ], [ {type: "Switch", args: {title: "Optic fiber", outvar: "optics", tip: "Use optic fiber instead of direct attach copper cable"}} @@ -291,16 +291,16 @@ const shop_data = { "if": [ {"var": "ext_data.has_other_dio"}, [ - {type: "Switch", args: {title: "Output first group", fallback: true, outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + {type: "Switch", args: {title: "Output first bank", fallback: true, outvar: "out_first_bank", tip: "Switch connectors 0-3 to output"}} ], [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + {type: "Switch", args: {title: "Output first bank", outvar: "out_first_bank", tip: "Switch connectors 0-3 to output"}} ] ] }, { "if": [ - {"!": {"var": "out_first_group"}}, + {"!": {"var": "out_first_bank"}}, {type: "Group", items: [ {type: "Switch", args: {title: "Termination #0", outvar: "term_0", tip: "Enable termination on channel #0"}}, {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on channel #1"}}, @@ -310,10 +310,10 @@ const shop_data = { null ] }, - {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}}, + {type: "Switch", args: {title: "Output second bank", outvar: "out_second_bank", fallback: true, tip: "Switch connectors 4-7 to output"}}, { "if": [ - {"!": {"var": "out_second_group"}}, + {"!": {"var": "out_second_bank"}}, {type: "Group", items: [ {type: "Switch", args: {title: "Termination #4", outvar: "term_4", tip: "Enable termination on channel #4"}}, {type: "Switch", args: {title: "Termination #5", outvar: "term_5", tip: "Enable termination on channel #5"}}, @@ -350,16 +350,16 @@ const shop_data = { "if": [ {"var": "ext_data.has_other_dio"}, [ - {type: "Switch", args: {title: "Output first group", fallback: true, outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + {type: "Switch", args: {title: "Output first bank", fallback: true, outvar: "out_first_bank", tip: "Switch connectors 0-3 to output"}} ], [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + {type: "Switch", args: {title: "Output first bank", outvar: "out_first_bank", tip: "Switch connectors 0-3 to output"}} ] ] }, { "if": [ - {"!": {"var": "out_first_group"}}, + {"!": {"var": "out_first_bank"}}, {type: "Group", items: [ {type: "Switch", args: {title: "Termination #0", outvar: "term_0", tip: "Enable termination on channel #0"}}, {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on channel #1"}}, @@ -369,10 +369,10 @@ const shop_data = { null ] }, - {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}}, + {type: "Switch", args: {title: "Output second bank", outvar: "out_second_bank", fallback: true, tip: "Switch connectors 4-7 to output"}}, { "if": [ - {"!": {"var": "out_second_group"}}, + {"!": {"var": "out_second_bank"}}, {type: "Group", items: [ {type: "Switch", args: {title: "Termination #4", outvar: "term_4", tip: "Enable termination on channel #4"}}, {type: "Switch", args: {title: "Termination #5", outvar: "term_5", tip: "Enable termination on channel #5"}}, @@ -421,16 +421,16 @@ const shop_data = { "if": [ {"var": "ext_data.has_other_dio"}, [ - {type: "Switch", args: {title: "Output first group", fallback: true, outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + {type: "Switch", args: {title: "Output first bank", fallback: true, outvar: "out_first_bank", tip: "Switch connectors 0-3 to output"}} ], [ - {type: "Switch", args: {title: "Output first group", outvar: "out_first_group", tip: "Switch connectors 0-3 to output"}} + {type: "Switch", args: {title: "Output first bank", outvar: "out_first_bank", tip: "Switch connectors 0-3 to output"}} ] ] }, { "if": [ - {"!": {"var": "out_first_group"}}, + {"!": {"var": "out_first_bank"}}, {type: "Group", items: [ {type: "Switch", args: {title: "Termination #0", outvar: "term_0", tip: "Enable termination on channel #0"}}, {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on channel #1"}}, @@ -440,10 +440,10 @@ const shop_data = { null ] }, - {type: "Switch", args: {title: "Output second group", outvar: "out_second_group", fallback: true, tip: "Switch connectors 4-7 to output"}}, + {type: "Switch", args: {title: "Output second bank", outvar: "out_second_bank", fallback: true, tip: "Switch connectors 4-7 to output"}}, { "if": [ - {"!": {"var": "out_second_group"}}, + {"!": {"var": "out_second_bank"}}, {type: "Group", items: [ {type: "Switch", args: {title: "Termination #4", outvar: "term_4", tip: "Enable termination on channel #4"}}, {type: "Switch", args: {title: "Termination #5", outvar: "term_5", tip: "Enable termination on channel #5"}}, @@ -453,10 +453,10 @@ const shop_data = { null ] }, - {type: "Switch", args: {title: "Output third group", outvar: "out_third_group", fallback: true, tip: "Switch connectors 8-11 to output"}}, + {type: "Switch", args: {title: "Output third bank", outvar: "out_third_bank", fallback: true, tip: "Switch connectors 8-11 to output"}}, { "if": [ - {"!": {"var": "out_third_group"}}, + {"!": {"var": "out_third_bank"}}, {type: "Group", items: [ {type: "Switch", args: {title: "Termination #8", outvar: "term_8", tip: "Enable termination on channel #8"}}, {type: "Switch", args: {title: "Termination #9", outvar: "term_9", tip: "Enable termination on channel #9"}}, @@ -466,10 +466,10 @@ const shop_data = { null ] }, - {type: "Switch", args: {title: "Output fourth group", outvar: "out_fourth_group", fallback: true, tip: "Switch connectors 12-15 to output"}}, + {type: "Switch", args: {title: "Output fourth bank", outvar: "out_fourth_bank", fallback: true, tip: "Switch connectors 12-15 to output"}}, { "if": [ - {"!": {"var": "out_fourth_group"}}, + {"!": {"var": "out_fourth_bank"}}, {type: "Group", items: [ {type: "Switch", args: {title: "Termination #12", outvar: "term_12", tip: "Enable termination on channel #12"}}, {type: "Switch", args: {title: "Termination #13", outvar: "term_13", tip: "Enable termination on channel #13"}}, -- 2.42.0 From 2480b9ad545704d2b97865538295c7ce21f163ac Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 26 Sep 2023 14:44:39 +0800 Subject: [PATCH 31/42] Leave opt-out option only to the first kasli Signed-off-by: Egor Savkin --- static/js/shop_components.jsx | 3 ++- static/js/shop_data.js | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index 65d2b1c..f81eb00 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -443,9 +443,10 @@ export function OptionsSummaryPopup({id, options, data}) { export function FillExtData(data, index) { return { + has_previous_carrier: data.filter((value, item_index) => index > item_index && value.name === "Carrier").length > 0, has_other_dio: data.filter((value, item_index) => index !== item_index && value.name.endsWith("-TTL")).length > 0, has_dds: data.filter(((value, _) => value.name === "DDS" && (!value.options_data || !value.options_data.mono_eem))).length > 0, - has_sampler: data.filter(((value, _) => value.name === "Sampler" && (!value.options_data || !value.options_data.mono_eem))).length > 0 + has_sampler: data.filter(((value, _) => value.name === "Sampler" && (!value.options_data || !value.options_data.mono_eem))).length > 0, } } diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 8a9ba72..65be0ac 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -79,7 +79,10 @@ const shop_data = { {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24", tip: "Set up IPv4 address used by core device"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}, tip: "Use external clock reference: 10, 80 (beta), 100 or 125 MHz. Other variants may be provided if needed."}}, - {type: "Switch", args: {title: "Opt out from promotional USB-stick", outvar: "usb_opt_out", tip: "Do not ship a promotional USB-stick"}}, + {"if": [ + {"!": {"var": "ext_data.has_previous_carrier"}}, + {type: "Switch", args: {title: "Opt out from promotional USB-stick", outvar: "usb_opt_out", tip: "Do not ship a promotional USB-stick"}} + ]} ], [ {type: "Switch", args: {title: "Optic fiber", outvar: "optics", tip: "Use optic fiber instead of direct attach copper cable"}} @@ -163,7 +166,10 @@ const shop_data = { {type: "Line", args: {title: "IPv4", outvar: "ipv4", fallback: "192.168.1.75/24", tip: "Set up IPv4 address used by core device"}}, {type: "SwitchLine", args: {title: "IPv6", outvar: "ipv6"}}, {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}, tip: "Use external clock reference: 10, 80 (beta), 100 or 125 MHz. Other variants may be provided if needed."}}, - {type: "Switch", args: {title: "Opt out from promotional USB-stick", outvar: "usb_opt_out", tip: "Do not ship a promotional USB-stick"}}, + {"if": [ + {"!": {"var": "ext_data.has_previous_carrier"}}, + {type: "Switch", args: {title: "Opt out from promotional USB-stick", outvar: "usb_opt_out", tip: "Do not ship a promotional USB-stick"}} + ]} ], [ {type: "Switch", args: {title: "Optic fiber", outvar: "optics", tip: "Use optic fiber instead of direct attach copper cable"}} -- 2.42.0 From 291332eaf4422aedf016e0729fecbf552090c25c Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 27 Sep 2023 16:37:09 +0800 Subject: [PATCH 32/42] Add HD68 cable options and fix first small cards options Signed-off-by: Egor Savkin --- sass/css/_shop.scss | 9 +++++++-- static/js/shop.jsx | 3 ++- static/js/shop_components.jsx | 6 +++--- static/js/shop_data.js | 6 ++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss index 3de09b5..4e5f0b8 100644 --- a/sass/css/_shop.scss +++ b/sass/css/_shop.scss @@ -533,14 +533,19 @@ button { .form-check { min-height: 1rem; } + + &.hd68-idc, &.stabilizer, &.clocker { + width: 85px; + left: -11px; // (card width (63) - overlay width (85)) / 2 + } } } .overlay-smallcard { - right: -38.5px; // (card width (63) - overlay width (140)) / 2 + left: -38.5px; // (card width (63) - overlay width (140)) / 2 } .overlay-bigcard { - right: -7px; // (card width (126) - overlay width (140)) / 2 + left: -7px; // (card width (126) - overlay width (140)) / 2 } .hovered { diff --git a/static/js/shop.jsx b/static/js/shop.jsx index 188f50c..feba830 100644 --- a/static/js/shop.jsx +++ b/static/js/shop.jsx @@ -705,9 +705,10 @@ class ProductCartItem extends React.PureComponent { ) : (options ? ( { // console.log("construct", outvar, value, options_data); diff --git a/static/js/shop_components.jsx b/static/js/shop_components.jsx index f81eb00..725e698 100644 --- a/static/js/shop_components.jsx +++ b/static/js/shop_components.jsx @@ -318,7 +318,7 @@ export function FilterOptions(options, data) { return target } -export function OptionsDialogPopup({options, data, target, id, big}) { +export function OptionsDialogPopup({options, data, target, id, big, options_class}) { const [show, setShow] = useState(false); const ref = useClickAway((e) => { if (e.type === "mousedown") // ignore touchstart @@ -326,7 +326,7 @@ export function OptionsDialogPopup({options, data, target, id, big}) { } ); - let div_classes = "overlayVariant border rounded " + (big ? "overlay-bigcard" : "overlay-smallcard") + let div_classes = "overlayVariant border rounded " + (big ? "overlay-bigcard " : "overlay-smallcard ") + (options_class || ""); const handleClick = (event) => { setShow(!show); }; @@ -444,7 +444,7 @@ export function OptionsSummaryPopup({id, options, data}) { export function FillExtData(data, index) { return { has_previous_carrier: data.filter((value, item_index) => index > item_index && value.name === "Carrier").length > 0, - has_other_dio: data.filter((value, item_index) => index !== item_index && value.name.endsWith("-TTL")).length > 0, + has_other_dio: data.filter((value, item_index) => index !== item_index && value.name &&value.name.endsWith("-TTL")).length > 0, has_dds: data.filter(((value, _) => value.name === "DDS" && (!value.options_data || !value.options_data.mono_eem))).length > 0, has_sampler: data.filter(((value, _) => value.name === "Sampler" && (!value.options_data || !value.options_data.mono_eem))).length > 0, } diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 65be0ac..caf9b3f 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -833,6 +833,10 @@ const shop_data = { size: 'small', type: 'hd68', hp: 4, + 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}}, + ], + options_class: "hd68-idc", nbrSlotMin: 1, nbrSlotMax: 4, nbrCurrentSlot: 0, @@ -955,6 +959,7 @@ const shop_data = { {type: "Switch", args: {title: "Ext CLK", outvar: "ext_clk"}}, {type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}} ], + options_class: "clocker", size: 'small', type: 'clocker', hp: 4, @@ -996,6 +1001,7 @@ const shop_data = { options: [ {type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}} ], + options_class: "stabilizer", size: 'small', type: null, hp: 4, -- 2.42.0 From 72c1b1747c9162bb26bf081e4ae8403f629cb3f5 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Thu, 28 Sep 2023 12:09:53 +0800 Subject: [PATCH 33/42] Add edge counter for the options to TTL Signed-off-by: Egor Savkin --- static/js/shop_data.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/static/js/shop_data.js b/static/js/shop_data.js index caf9b3f..f049c98 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -328,6 +328,12 @@ const shop_data = { ]}, null ] + }, + { + "if": [ + {"!": {"and": [{"var": "out_first_bank"}, {"var": "out_second_bank"}]}}, + {type: "Switch", args: {title: "Edge counter", outvar: "edge_counter", tip: "Enable edge counter for inputs"}} + ] } ], rules: { @@ -387,6 +393,12 @@ const shop_data = { ]}, null ] + }, + { + "if": [ + {"!": {"and": [{"var": "out_first_bank"}, {"var": "out_second_bank"}]}}, + {type: "Switch", args: {title: "Edge counter", outvar: "edge_counter", tip: "Enable edge counter for inputs"}} + ] } ], size: 'small', @@ -442,8 +454,7 @@ const shop_data = { {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on channel #1"}}, {type: "Switch", args: {title: "Termination #2", outvar: "term_2", tip: "Enable termination on channel #2"}}, {type: "Switch", args: {title: "Termination #3", outvar: "term_3", tip: "Enable termination on channel #3"}}, - ]}, - null + ]} ] }, {type: "Switch", args: {title: "Output second bank", outvar: "out_second_bank", fallback: true, tip: "Switch connectors 4-7 to output"}}, @@ -455,8 +466,7 @@ const shop_data = { {type: "Switch", args: {title: "Termination #5", outvar: "term_5", tip: "Enable termination on channel #5"}}, {type: "Switch", args: {title: "Termination #6", outvar: "term_6", tip: "Enable termination on channel #6"}}, {type: "Switch", args: {title: "Termination #7", outvar: "term_7", tip: "Enable termination on channel #7"}}, - ]}, - null + ]} ] }, {type: "Switch", args: {title: "Output third bank", outvar: "out_third_bank", fallback: true, tip: "Switch connectors 8-11 to output"}}, @@ -468,8 +478,7 @@ const shop_data = { {type: "Switch", args: {title: "Termination #9", outvar: "term_9", tip: "Enable termination on channel #9"}}, {type: "Switch", args: {title: "Termination #10", outvar: "term_10", tip: "Enable termination on channel #10"}}, {type: "Switch", args: {title: "Termination #11", outvar: "term_11", tip: "Enable termination on channel #11"}}, - ]}, - null + ]} ] }, {type: "Switch", args: {title: "Output fourth bank", outvar: "out_fourth_bank", fallback: true, tip: "Switch connectors 12-15 to output"}}, @@ -481,8 +490,13 @@ const shop_data = { {type: "Switch", args: {title: "Termination #13", outvar: "term_13", tip: "Enable termination on channel #13"}}, {type: "Switch", args: {title: "Termination #14", outvar: "term_14", tip: "Enable termination on channel #14"}}, {type: "Switch", args: {title: "Termination #15", outvar: "term_15", tip: "Enable termination on channel #15"}}, - ]}, - null + ]} + ] + }, + { + "if": [ + {"!": {"and": [{"var": "out_first_bank"}, {"var": "out_second_bank"}, {"var": "out_third_bank"}, {"var": "out_fourth_bank"}]}}, + {type: "Switch", args: {title: "Edge counter", outvar: "edge_counter", tip: "Enable edge counter for inputs"}} ] } ], -- 2.42.0 From e3a50f1b9a614e33c3d26d32ca0e1197a8ac921c Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 11 Oct 2023 13:00:57 +0800 Subject: [PATCH 34/42] Add options to zotino, thermostat, sampler and pounder Signed-off-by: Egor Savkin --- static/js/shop_data.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/static/js/shop_data.js b/static/js/shop_data.js index f049c98..3aa1168 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -670,6 +670,9 @@ const shop_data = { 'Channels can also be broken out to BNC or SMA using IDC-BNC, IDC-SMA or IDC-MCX cards.', 'DAC temperature can be stabilized using the Sinara 8451 Thermostat (sold separately).' ], + options: [ + {type: "Switch", args: {title: "TEC chip", outvar: "tec_chip", tip: "Used for stabilizing temperature with Sinara 8451 Thermostat"}}, + ], datasheet_file: '/docs/sinara-datasheets/5432.pdf', datasheet_name: '5432 Zotino datasheet', size: 'small', @@ -902,6 +905,21 @@ const shop_data = { {type: "Switch", args: {title: "SUServo mode", outvar: "suservo"}}, null ] + }, + {type: "Switch", args: {title: "Configure termination", outvar: "config_term"}}, + { + "if": [ + {"var": "config_term"}, + {type: "Group", items: [ + {type: "Switch", args: {title: "Termination #0", outvar: "term_0", tip: "Enable termination on channel #0"}}, + {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on channel #1"}}, + {type: "Switch", args: {title: "Termination #2", outvar: "term_2", tip: "Enable termination on channel #2"}}, + {type: "Switch", args: {title: "Termination #3", outvar: "term_3", tip: "Enable termination on channel #3"}}, + {type: "Switch", args: {title: "Termination #4", outvar: "term_4", tip: "Enable termination on channel #4"}}, + {type: "Switch", args: {title: "Termination #5", outvar: "term_5", tip: "Enable termination on channel #5"}}, + {type: "Switch", args: {title: "Termination #6", outvar: "term_6", tip: "Enable termination on channel #6"}}, + {type: "Switch", args: {title: "Termination #7", outvar: "term_7", tip: "Enable termination on channel #7"}}, + ]}] } ], size: 'big', @@ -1107,6 +1125,9 @@ const shop_data = { 'Up to 16W (+4A 4V) from MAX1969 drivers.', '100Base-T Ethernet with PoE.' ], + options: [ + {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, hp: 4, @@ -1161,7 +1182,8 @@ const shop_data = { 'AD9959 DDS (500MSPS, 10-bit).' ], options: [ - {type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}} + {type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}}, + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}} ], size: 'big', type: null, -- 2.42.0 From 159d4b631aa2a6454bd1a0f3c246ca9597a3b400 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 18 Oct 2023 10:34:01 +0800 Subject: [PATCH 35/42] Add phaser baseband/upconverter variants Signed-off-by: Egor Savkin --- static/js/shop_data.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 3aa1168..0e8cc1f 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -635,7 +635,8 @@ const shop_data = { 'The upconverter is optional, if you would like the baseband version please leave us a note.' ], options: [ - {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}} + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, + {type: "Radio", args: {title: "Variant", outvar: "variant", variants: ["Baseband", "Upconverter"], fallback: 1}}, ], size: 'small', type: 'urukul', -- 2.42.0 From 281f0a26f0a5086041f1b6bb9f9325e3d555205a Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 1 Nov 2023 15:41:53 +0800 Subject: [PATCH 36/42] Add termination choices to stabilizer Signed-off-by: Egor Savkin --- static/js/shop_data.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/static/js/shop_data.js b/static/js/shop_data.js index 0e8cc1f..b57c163 100644 --- a/static/js/shop_data.js +++ b/static/js/shop_data.js @@ -1032,7 +1032,9 @@ const shop_data = { 'Can be controlled by Kasli or work stand-alone with PoE supply.' ], options: [ - {type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}} + {type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}}, + {type: "Switch", args: {title: "Term #0", outvar: "term_0", tip: "Enable termination on ADC channel #0"}}, + {type: "Switch", args: {title: "Term #1", outvar: "term_1", tip: "Enable termination on ADC channel #1"}} ], options_class: "stabilizer", size: 'small', @@ -1184,7 +1186,9 @@ const shop_data = { ], options: [ {type: "Switch", args: {title: "Ext power", outvar: "ext_pwr", "tip": "Use external power supply in order to reduce number of used EEM connectors"}}, - {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}} + {type: "SwitchLine", args: {title: "Ext CLK", outvar: "ext_clk", fallback: {text: "125 MHz", checked: false}}}, + {type: "Switch", args: {title: "Termination #0", outvar: "term_0", tip: "Enable termination on ADC channel #0"}}, + {type: "Switch", args: {title: "Termination #1", outvar: "term_1", tip: "Enable termination on ADC channel #1"}} ], size: 'big', type: null, -- 2.42.0 From a4ff9f70571b706d36a9922024b7f2b31f6c3673 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Wed, 8 Nov 2023 11:12:32 +0800 Subject: [PATCH 37/42] Rebase and fix warning in development mode Signed-off-by: Egor Savkin --- package-lock.json | 792 ++++++++++++++++++++------------------- package.json | 18 +- static/js/shop.bundle.js | 2 +- static/js/shop.jsx | 122 +++--- 4 files changed, 465 insertions(+), 469 deletions(-) diff --git a/package-lock.json b/package-lock.json index d5f7465..d5090d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,12 @@ "name": "m-labs-zola", "version": "1.0.0", "devDependencies": { - "@babel/cli": "^7.22.6", - "@babel/core": "^7.22.8", - "@babel/preset-env": "^7.22.7", - "@babel/preset-react": "^7.22.5", - "@uidotdev/usehooks": "^2.1.1", - "axios": "^1.4.0", + "@babel/cli": "^7.23.0", + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-react": "^7.22.15", + "@uidotdev/usehooks": "^2.4.1", + "axios": "^1.6.0", "babel-loader": "^9.1.3", "babel-preset-minify": "^0.5.2", "bootstrap": "^5.3.0", @@ -22,10 +22,10 @@ "prop-types": "^15.8.1", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.1", - "react-bootstrap": "^2.8.0", + "react-bootstrap": "^2.9.1", "react-dom": "^18.2.0", - "uuid": "^9.0.0", - "webpack": "^5.88.1", + "uuid": "^9.0.1", + "webpack": "^5.89.0", "webpack-cli": "^5.1.4" } }, @@ -43,14 +43,14 @@ } }, "node_modules/@babel/cli": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.22.6.tgz", - "integrity": "sha512-Be3/RfEDmkMRGT1+ru5nTkfcvWz5jDOYg1V9rXqTz2u9Qt96O1ryboGvxVBp7wOnYWDB8DNHIWb6DThrpudfOw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.23.0.tgz", + "integrity": "sha512-17E1oSkGk2IwNILM4jtfAvgjt+ohmpfBky8aLerUfYZhiPNg7ca+CRCxZn8QDxwNhV/upsc2VHBCqGFIR+iBfA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", "commander": "^4.0.1", - "convert-source-map": "^1.1.0", + "convert-source-map": "^2.0.0", "fs-readdir-recursive": "^1.1.0", "glob": "^7.2.0", "make-dir": "^2.1.0", @@ -72,47 +72,48 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz", - "integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.8.tgz", - "integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-module-transforms": "^7.22.5", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -122,13 +123,22 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -162,16 +172,45 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz", - "integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-validator-option": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", "browserslist": "^4.21.9", - "lru-cache": "^5.1.1" + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -180,27 +219,13 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.6.tgz", - "integrity": "sha512-iwdzgtSiBxF6ni6mzVnZCF3xt5qE6cEA0J7nFt8QOAWZ0zjCFceEgpn3vtb2V7WFR6QzP2jmIFOHMTRo7eNJjQ==", + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@nicolo-ribaudo/semver-v6": "^6.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "bin": { + "semver": "bin/semver.js" } }, "node_modules/@babel/helper-create-regexp-features-plugin": { @@ -221,9 +246,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz", - "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", + "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -233,26 +258,26 @@ "resolve": "^1.14.2" }, "peerDependencies": { - "@babel/core": "^7.4.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -271,46 +296,46 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", - "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", - "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-optimise-call-expression": { @@ -335,15 +360,14 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.5.tgz", - "integrity": "sha512-cU0Sq1Rf4Z55fgz7haOakIyM7+x/uCFwXpLPaeRzfoUtAEAuUZjZvFPjL/rk5rW693dIgn2hng1W7xbT7lWT4g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-wrap-function": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -353,20 +377,20 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz", - "integrity": "sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-simple-access": { @@ -415,60 +439,59 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.5.tgz", - "integrity": "sha512-bYqLIBSEshYcYQyfks8ewYA8S30yaGSeRslcvKMvoUk6HHPySbxHq9YRi6ghhzEU+yhQv9bP/jXnygkStOcqZw==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", "dev": true, "dependencies": { "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -476,9 +499,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -488,9 +511,9 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz", - "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", + "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -503,14 +526,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", - "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", + "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.5" + "@babel/plugin-transform-optional-chaining": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -531,22 +554,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -813,14 +820,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.7.tgz", - "integrity": "sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", + "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -863,9 +870,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz", - "integrity": "sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", + "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -894,12 +901,12 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz", - "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", + "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, @@ -911,18 +918,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", - "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", + "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, @@ -950,9 +957,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz", - "integrity": "sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", + "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -996,9 +1003,9 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz", - "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", + "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1028,9 +1035,9 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz", - "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", + "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1044,9 +1051,9 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", - "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", + "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1076,9 +1083,9 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", - "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", + "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1107,9 +1114,9 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz", - "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", + "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1138,12 +1145,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", - "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", + "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1154,12 +1161,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", - "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-simple-access": "^7.22.5" }, @@ -1171,15 +1178,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", - "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", + "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1236,9 +1243,9 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz", - "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", + "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1252,9 +1259,9 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz", - "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", + "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1268,16 +1275,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz", - "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", + "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.5", + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.22.5" + "@babel/plugin-transform-parameters": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1303,9 +1310,9 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz", - "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", + "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1319,9 +1326,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz", - "integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", + "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1336,9 +1343,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", - "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", + "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1367,13 +1374,13 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz", - "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", + "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, @@ -1415,16 +1422,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", - "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz", + "integrity": "sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1465,13 +1472,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz", - "integrity": "sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "regenerator-transform": "^0.15.1" + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -1572,9 +1579,9 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz", - "integrity": "sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1635,17 +1642,17 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.7.tgz", - "integrity": "sha512-1whfDtW+CzhETuzYXfcgZAh8/GFMeEbz0V5dVgya8YeJyCU6Y/P2Gnx4Qb3MylK68Zu9UiwUvbPMPTpFAOJ+sQ==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz", + "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-compilation-targets": "^7.22.6", + "@babel/compat-data": "^7.23.2", + "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", @@ -1666,60 +1673,60 @@ "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.22.5", - "@babel/plugin-transform-async-generator-functions": "^7.22.7", + "@babel/plugin-transform-async-generator-functions": "^7.23.2", "@babel/plugin-transform-async-to-generator": "^7.22.5", "@babel/plugin-transform-block-scoped-functions": "^7.22.5", - "@babel/plugin-transform-block-scoping": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.23.0", "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-class-static-block": "^7.22.5", - "@babel/plugin-transform-classes": "^7.22.6", + "@babel/plugin-transform-class-static-block": "^7.22.11", + "@babel/plugin-transform-classes": "^7.22.15", "@babel/plugin-transform-computed-properties": "^7.22.5", - "@babel/plugin-transform-destructuring": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.23.0", "@babel/plugin-transform-dotall-regex": "^7.22.5", "@babel/plugin-transform-duplicate-keys": "^7.22.5", - "@babel/plugin-transform-dynamic-import": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.11", "@babel/plugin-transform-exponentiation-operator": "^7.22.5", - "@babel/plugin-transform-export-namespace-from": "^7.22.5", - "@babel/plugin-transform-for-of": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-for-of": "^7.22.15", "@babel/plugin-transform-function-name": "^7.22.5", - "@babel/plugin-transform-json-strings": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.11", "@babel/plugin-transform-literals": "^7.22.5", - "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", "@babel/plugin-transform-member-expression-literals": "^7.22.5", - "@babel/plugin-transform-modules-amd": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.22.5", - "@babel/plugin-transform-modules-systemjs": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.23.0", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-modules-systemjs": "^7.23.0", "@babel/plugin-transform-modules-umd": "^7.22.5", "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", "@babel/plugin-transform-new-target": "^7.22.5", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", - "@babel/plugin-transform-numeric-separator": "^7.22.5", - "@babel/plugin-transform-object-rest-spread": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-numeric-separator": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.22.15", "@babel/plugin-transform-object-super": "^7.22.5", - "@babel/plugin-transform-optional-catch-binding": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.6", - "@babel/plugin-transform-parameters": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-parameters": "^7.22.15", "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", "@babel/plugin-transform-property-literals": "^7.22.5", - "@babel/plugin-transform-regenerator": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", "@babel/plugin-transform-reserved-words": "^7.22.5", "@babel/plugin-transform-shorthand-properties": "^7.22.5", "@babel/plugin-transform-spread": "^7.22.5", "@babel/plugin-transform-sticky-regex": "^7.22.5", "@babel/plugin-transform-template-literals": "^7.22.5", "@babel/plugin-transform-typeof-symbol": "^7.22.5", - "@babel/plugin-transform-unicode-escapes": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", "@babel/plugin-transform-unicode-property-regex": "^7.22.5", "@babel/plugin-transform-unicode-regex": "^7.22.5", "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", - "babel-plugin-polyfill-corejs2": "^0.4.4", - "babel-plugin-polyfill-corejs3": "^0.8.2", - "babel-plugin-polyfill-regenerator": "^0.5.1", - "core-js-compat": "^3.31.0" + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.23.0", + "babel-plugin-polyfill-corejs2": "^0.4.6", + "babel-plugin-polyfill-corejs3": "^0.8.5", + "babel-plugin-polyfill-regenerator": "^0.5.3", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -1728,32 +1735,39 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/preset-react": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", - "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.15.tgz", + "integrity": "sha512-Csy1IJ2uEh/PecCBXXoZGAZBeCATTuePzCSB7dLYWS0vOEj6CNpjxIhW4duWwZodBNueH7QO14WbGn8YyeuN9w==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", "@babel/plugin-transform-react-display-name": "^7.22.5", - "@babel/plugin-transform-react-jsx": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.15", "@babel/plugin-transform-react-jsx-development": "^7.22.5", "@babel/plugin-transform-react-pure-annotations": "^7.22.5" }, @@ -1783,33 +1797,33 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1818,13 +1832,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2095,9 +2109,9 @@ "dev": true }, "node_modules/@uidotdev/usehooks": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.1.1.tgz", - "integrity": "sha512-sVJ1jXU62Edh22dREEa3mHcHnH2MUgokuzLw9guNS30ADCkdhYASNZxg2V8iB83iwY5H+jSeSxjqGaFvsRrNBQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz", + "integrity": "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==", "dev": true, "engines": { "node": ">=16" @@ -2408,9 +2422,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -2572,42 +2586,51 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.4.tgz", - "integrity": "sha512-9WeK9snM1BfxB38goUEv2FLnA6ja07UMfazFHzCXUb3NyDZAwfXvQiURQ6guTTMeHcOsdknULm1PDhs4uWtKyA==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", + "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.1", - "@nicolo-ribaudo/semver-v6": "^6.3.3" + "@babel/helper-define-polyfill-provider": "^0.4.3", + "semver": "^6.3.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.2.tgz", - "integrity": "sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", + "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.1", - "core-js-compat": "^3.31.0" + "@babel/helper-define-polyfill-provider": "^0.4.3", + "core-js-compat": "^3.33.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.1.tgz", - "integrity": "sha512-L8OyySuI6OSQ5hFy9O+7zFjyr4WhAfRjLIOkhQGYl+emwJkd/S4XXT1JpfrgR1jrQ1NcGiOh+yAdGlF8pnC3Jw==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", + "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.1" + "@babel/helper-define-polyfill-provider": "^0.4.3" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-transform-inline-consecutive-adds": { @@ -2730,9 +2753,9 @@ } }, "node_modules/bootstrap": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz", - "integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz", + "integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==", "dev": true, "funding": [ { @@ -2745,7 +2768,7 @@ } ], "peerDependencies": { - "@popperjs/core": "^2.11.7" + "@popperjs/core": "^2.11.8" } }, "node_modules/brace-expansion": { @@ -2772,9 +2795,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "dev": true, "funding": [ { @@ -2791,10 +2814,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -2810,9 +2833,9 @@ "dev": true }, "node_modules/caniuse-lite": { - "version": "1.0.30001514", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001514.tgz", - "integrity": "sha512-ENcIpYBmwAAOm/V2cXgM7rZUrKKaqisZl4ZAI520FIkqGXUxJjmaIssbRW5HVVR5tyV6ygTLIm15aU8LUmQSaQ==", + "version": "1.0.30001561", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz", + "integrity": "sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==", "dev": true, "funding": [ { @@ -2955,21 +2978,18 @@ "dev": true }, "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true }, "node_modules/core-js-compat": { - "version": "3.31.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.31.1.tgz", - "integrity": "sha512-wIDWd2s5/5aJSdpOJHfSibxNODxoGoWOBHt8JSPB41NOE94M7kuTPZCYLOlTtuoXTsBPKobpJ6T+y0SSy5L9SA==", + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.2.tgz", + "integrity": "sha512-axfo+wxFVxnqf8RvxTzoAlzW4gRoacrHeoFlc9n0x50+7BEyZL/Rt3hicaED1/CEd7I6tPCPVUYcJwCMO5XUYw==", "dev": true, "dependencies": { - "browserslist": "^4.21.9" + "browserslist": "^4.22.1" }, "funding": { "type": "opencollective", @@ -3051,9 +3071,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.454", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.454.tgz", - "integrity": "sha512-pmf1rbAStw8UEQ0sr2cdJtWl48ZMuPD9Sto8HVQOq9vx9j2WgDEN6lYoaqFvqEHYOmGA9oRGn7LqWI9ta0YugQ==", + "version": "1.4.578", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.578.tgz", + "integrity": "sha512-V0ZhSu1BQZKfG0yNEL6Dadzik8E1vAzfpVOapdSiT9F6yapEJ3Bk+4tZ4SMPdWiUchCgnM/ByYtBzp5ntzDMIA==", "dev": true }, "node_modules/enhanced-resolve": { @@ -3647,9 +3667,9 @@ } }, "node_modules/jquery": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz", - "integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", "dev": true }, "node_modules/js-tokens": { @@ -4083,15 +4103,15 @@ } }, "node_modules/react-bootstrap": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz", - "integrity": "sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.9.1.tgz", + "integrity": "sha512-ezgmh/ARCYp18LbZEqPp0ppvy+ytCmycDORqc8vXSKYV3cer4VH7OReV8uMOoKXmYzivJTxgzGHalGrHamryHA==", "dev": true, "dependencies": { - "@babel/runtime": "^7.21.0", + "@babel/runtime": "^7.22.5", "@restart/hooks": "^0.4.9", - "@restart/ui": "^1.6.3", - "@types/react-transition-group": "^4.4.5", + "@restart/ui": "^1.6.6", + "@types/react-transition-group": "^4.4.6", "classnames": "^2.3.2", "dom-helpers": "^5.2.1", "invariant": "^2.2.4", @@ -4237,9 +4257,9 @@ "dev": true }, "node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" @@ -4673,9 +4693,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -4721,10 +4741,14 @@ } }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -4752,9 +4776,9 @@ } }, "node_modules/webpack": { - "version": "5.88.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz", - "integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", diff --git a/package.json b/package.json index 0bec725..0fad848 100644 --- a/package.json +++ b/package.json @@ -12,25 +12,25 @@ "url": "https://git.m-labs.hk/M-Labs/web2019.git" }, "devDependencies": { - "@babel/cli": "^7.22.6", - "@babel/core": "^7.22.8", - "@babel/preset-env": "^7.22.7", - "@babel/preset-react": "^7.22.5", - "axios": "^1.4.0", + "@babel/cli": "^7.23.0", + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-react": "^7.22.15", + "axios": "^1.6.0", "babel-loader": "^9.1.3", "babel-preset-minify": "^0.5.2", "bootstrap": "^5.3.0", "jquery": "^3.7.0", "prop-types": "^15.8.1", "react": "^18.2.0", - "react-bootstrap": "^2.8.0", + "react-bootstrap": "^2.9.1", "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", - "uuid": "^9.0.0", - "webpack": "^5.88.1", + "uuid": "^9.0.1", + "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "json-logic-js": "^2.0.2", - "@uidotdev/usehooks": "^2.1.1" + "@uidotdev/usehooks": "^2.4.1" }, "babel": { "presets": [ diff --git a/static/js/shop.bundle.js b/static/js/shop.bundle.js index 745b3d0..1aef3de 100644 --- a/static/js/shop.bundle.js +++ b/static/js/shop.bundle.js @@ -1,2 +1,2 @@ /*! For license information please see shop.bundle.js.LICENSE.txt */ -(()=>{var e={184:(e,t)=>{var n;!function(){"use strict";var r={}.hasOwnProperty;function o(){for(var e=[],t=0;t{"use strict";var r=n(296),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function u(e){return r.isMemo(e)?i:l[e.$$typeof]||o}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=i;var s=Object.defineProperty,c=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var o=p(n);o&&o!==m&&e(t,o,r)}var i=c(n);d&&(i=i.concat(d(n)));for(var l=u(t),h=u(n),g=0;g{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,o=n?Symbol.for("react.portal"):60106,a=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,l=n?Symbol.for("react.profiler"):60114,u=n?Symbol.for("react.provider"):60109,s=n?Symbol.for("react.context"):60110,c=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,f=n?Symbol.for("react.forward_ref"):60112,p=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,h=n?Symbol.for("react.memo"):60115,g=n?Symbol.for("react.lazy"):60116,v=n?Symbol.for("react.block"):60121,b=n?Symbol.for("react.fundamental"):60117,y=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function E(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case c:case d:case a:case l:case i:case p:return e;default:switch(e=e&&e.$$typeof){case s:case f:case g:case h:case u:return e;default:return t}}case o:return t}}}function x(e){return E(e)===d}t.AsyncMode=c,t.ConcurrentMode=d,t.ContextConsumer=s,t.ContextProvider=u,t.Element=r,t.ForwardRef=f,t.Fragment=a,t.Lazy=g,t.Memo=h,t.Portal=o,t.Profiler=l,t.StrictMode=i,t.Suspense=p,t.isAsyncMode=function(e){return x(e)||E(e)===c},t.isConcurrentMode=x,t.isContextConsumer=function(e){return E(e)===s},t.isContextProvider=function(e){return E(e)===u},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return E(e)===f},t.isFragment=function(e){return E(e)===a},t.isLazy=function(e){return E(e)===g},t.isMemo=function(e){return E(e)===h},t.isPortal=function(e){return E(e)===o},t.isProfiler=function(e){return E(e)===l},t.isStrictMode=function(e){return E(e)===i},t.isSuspense=function(e){return E(e)===p},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===a||e===d||e===l||e===i||e===p||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===g||e.$$typeof===h||e.$$typeof===u||e.$$typeof===s||e.$$typeof===f||e.$$typeof===b||e.$$typeof===y||e.$$typeof===w||e.$$typeof===v)},t.typeOf=E},296:(e,t,n)=>{"use strict";e.exports=n(103)},143:e=>{"use strict";e.exports=function(e,t,n,r,o,a,i,l){if(!e){var u;if(void 0===t)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var s=[n,r,o,a,i,l],c=0;(u=new Error(t.replace(/%s/g,(function(){return s[c++]})))).name="Invariant Violation"}throw u.framesToPop=1,u}}},703:(e,t,n)=>{"use strict";var r=n(414);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},697:(e,t,n)=>{e.exports=n(703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},448:(e,t,n)=>{"use strict";var r=n(294),o=n(840);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n
) : null - } - rootClose - > -
- {warning && ()} -
- - -
- - {warning ? ( - - ) : (options ? ( { - // console.log("construct", outvar, value, options_data); - options_data[outvar] = value; - }), - update: ((outvar, value) => { - // console.log("update", outvar, value, options_data); - if (outvar in options_data) options_data[outvar] = value; - onCardUpdate(); - }) - }} - />) : null) } - - - - {warning && model.showWarning && ( -
+ placement="bottom" + trigger={warning ? ['click', 'hover', 'focus'] : []} + overlay={ + ({arrowProps, hasDoneInitialMeasure, show, ...props}) => ( +

{warning.message}

-
- )} -
+
) + } + rootClose + > +
+ {warning ? + () : + (options && ( + { + // console.log("construct", outvar, value, options_data); + options_data[outvar] = value; + }), + update: ((outvar, value) => { + // console.log("update", outvar, value, options_data); + if (outvar in options_data) options_data[outvar] = value; + onCardUpdate(); + }) + }} + /> + )) + } +
+
{model.name_number}
@@ -761,7 +734,7 @@ class ProductCartItem extends React.PureComponent { (
{render_progress}
)} rootClose >
@@ -2451,8 +2424,7 @@ class Shop extends React.PureComponent { itemHovered={currentItemHovered} onToggleOverlayRemove={this.handleToggleOverlayRemove} onClickRemoveItem={this.handleDeleteItem} - onClickItem={this.handleShowOverlayRemove}> - onClickRemoveItem={this.handleDeleteItem} + onClickItem={this.handleShowOverlayRemove} onCardUpdate={this.handleCardsUpdated}> } -- 2.42.0 From f11ebc1152ffb43ef9ec6f377128b4e65aa72ada Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Tue, 21 Nov 2023 14:34:50 +0800 Subject: [PATCH 38/42] Update options * Separate Urukul 4412 * Add options for LVDS TTL * Remove usb flash option * Add cable lengths for fiber and copper options * Add IP option for Stabilizer and Pounder * Added note that most options can be changed after shipment Signed-off-by: Egor Savkin --- static/images/shop/graphic-03_Urukul-4412.svg | 1 + static/js/shop.bundle.js | 2 +- static/js/shop.jsx | 2 +- static/js/shop_components.jsx | 3 +- static/js/shop_data.js | 139 +++++++++++++++--- 5 files changed, 126 insertions(+), 21 deletions(-) create mode 100644 static/images/shop/graphic-03_Urukul-4412.svg diff --git a/static/images/shop/graphic-03_Urukul-4412.svg b/static/images/shop/graphic-03_Urukul-4412.svg new file mode 100644 index 0000000..f95bffd --- /dev/null +++ b/static/images/shop/graphic-03_Urukul-4412.svg @@ -0,0 +1 @@ + diff --git a/static/js/shop.bundle.js b/static/js/shop.bundle.js index 1aef3de..245ca50 100644 --- a/static/js/shop.bundle.js +++ b/static/js/shop.bundle.js @@ -1,2 +1,2 @@ /*! For license information please see shop.bundle.js.LICENSE.txt */ -(()=>{var e={184:(e,t)=>{var n;!function(){"use strict";var r={}.hasOwnProperty;function o(){for(var e=[],t=0;t{"use strict";var r=n(296),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function u(e){return r.isMemo(e)?i:l[e.$$typeof]||o}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=i;var s=Object.defineProperty,c=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var o=p(n);o&&o!==m&&e(t,o,r)}var i=c(n);d&&(i=i.concat(d(n)));for(var l=u(t),h=u(n),g=0;g{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,o=n?Symbol.for("react.portal"):60106,a=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,l=n?Symbol.for("react.profiler"):60114,u=n?Symbol.for("react.provider"):60109,s=n?Symbol.for("react.context"):60110,c=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,f=n?Symbol.for("react.forward_ref"):60112,p=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,h=n?Symbol.for("react.memo"):60115,g=n?Symbol.for("react.lazy"):60116,v=n?Symbol.for("react.block"):60121,b=n?Symbol.for("react.fundamental"):60117,y=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function E(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case c:case d:case a:case l:case i:case p:return e;default:switch(e=e&&e.$$typeof){case s:case f:case g:case h:case u:return e;default:return t}}case o:return t}}}function x(e){return E(e)===d}t.AsyncMode=c,t.ConcurrentMode=d,t.ContextConsumer=s,t.ContextProvider=u,t.Element=r,t.ForwardRef=f,t.Fragment=a,t.Lazy=g,t.Memo=h,t.Portal=o,t.Profiler=l,t.StrictMode=i,t.Suspense=p,t.isAsyncMode=function(e){return x(e)||E(e)===c},t.isConcurrentMode=x,t.isContextConsumer=function(e){return E(e)===s},t.isContextProvider=function(e){return E(e)===u},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return E(e)===f},t.isFragment=function(e){return E(e)===a},t.isLazy=function(e){return E(e)===g},t.isMemo=function(e){return E(e)===h},t.isPortal=function(e){return E(e)===o},t.isProfiler=function(e){return E(e)===l},t.isStrictMode=function(e){return E(e)===i},t.isSuspense=function(e){return E(e)===p},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===a||e===d||e===l||e===i||e===p||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===g||e.$$typeof===h||e.$$typeof===u||e.$$typeof===s||e.$$typeof===f||e.$$typeof===b||e.$$typeof===y||e.$$typeof===w||e.$$typeof===v)},t.typeOf=E},296:(e,t,n)=>{"use strict";e.exports=n(103)},143:e=>{"use strict";e.exports=function(e,t,n,r,o,a,i,l){if(!e){var u;if(void 0===t)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var s=[n,r,o,a,i,l],c=0;(u=new Error(t.replace(/%s/g,(function(){return s[c++]})))).name="Invariant Violation"}throw u.framesToPop=1,u}}},962:function(e,t,n){var r,o;r=function(){"use strict";Array.isArray||(Array.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)});var e={},t={"==":function(e,t){return e==t},"===":function(e,t){return e===t},"!=":function(e,t){return e!=t},"!==":function(e,t){return e!==t},">":function(e,t){return e>t},">=":function(e,t){return e>=t},"<":function(e,t,n){return void 0===n?e=t?[]:r}};return e.is_logic=function(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)&&1===Object.keys(e).length},e.truthy=function(e){return!(Array.isArray(e)&&0===e.length||!e)},e.get_operator=function(e){return Object.keys(e)[0]},e.get_values=function(t){return t[e.get_operator(t)]},e.apply=function(n,r){if(Array.isArray(n))return n.map((function(t){return e.apply(t,r)}));if(!e.is_logic(n))return n;var o,a,i,l,u,s=e.get_operator(n),c=n[s];if(Array.isArray(c)||(c=[c]),"if"===s||"?:"==s){for(o=0;o0){var d=String(s).split("."),f=t;for(o=0;o{"use strict";var r=n(414);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},697:(e,t,n)=>{e.exports=n(703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},448:(e,t,n)=>{"use strict";var r=n(294),o=n(840);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n