From d543e5432606e859c78501d01269a9739d3f9edd Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Thu, 17 Aug 2023 14:42:47 +0800 Subject: [PATCH] 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',