Add options for the cards #93
19
package.json
19
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": {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
|||
</div>
|
||||
</OverlayTrigger>
|
||||
|
||||
<div
|
||||
className="progress-container warning"
|
||||
onMouseEnter={this.handleOnMouseEnterWarningItem.bind(this, index, warning)}
|
||||
onMouseLeave={this.handleOnMouseLeaveWarningItem.bind(this, index, warning)}>
|
||||
|
||||
{warning ? (
|
||||
<img className="alert-warning" src={`/images${warning.icon}`} />
|
||||
) : (options ? <img className="alert-info" src="/images/shop/icon-customize.svg" /> : null) }
|
||||
|
||||
{options ? (
|
||||
<div
|
||||
style={{'display': (model.showOverlayRemove && options) ? 'flex' : 'none'}}
|
||||
className="overlayVariant">
|
||||
|
||||
{ProcessOptions({options: options, data: options_data, target: options_data})}
|
||||
</div>
|
||||
) : null }
|
||||
|
||||
|
||||
|
||||
{warning && model.showWarning && (
|
||||
<div className={`k-popup-warning ${shouldTooltipWarningClassInverted ? 'inverted': ''}`}>
|
||||
<p className="rule warning">
|
||||
<i>{warning.message}</i>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<h6>{model.name_number}</h6>
|
||||
|
||||
|
@ -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 (
|
||||
<ProductCartItem
|
||||
isMobile={isMobile}
|
||||
|
@ -1400,12 +1440,18 @@ class OrderSumary extends React.PureComponent {
|
|||
</button>
|
||||
</div>
|
||||
|
||||
{warning && (
|
||||
{warning ? (
|
||||
<img
|
||||
style={{'marginLeft': '10px'}}
|
||||
className="alert-warning"
|
||||
src={`/images/${warning.icon}`}
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
style={{'marginLeft': '10px'}}
|
||||
className="alert-warning"
|
||||
src="/images/shop/icon-customize.svg"
|
||||
/>
|
||||
)}
|
||||
|
||||
{!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) {
|
||||
|
|
|
@ -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 (
|
||||
<div className="shop-radio" key={uuidv4()}>
|
||||
{title}
|
||||
{variants.map((variant, _) => (
|
||||
<div className="form-check" key={outvar + variant}>
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="radio"
|
||||
name={outvar}
|
||||
id={outvar + variant}
|
||||
checked={target[outvar] === variant}
|
||||
onClick={() => handleClick(variant)}
|
||||
onChange={() => handleClick(variant)}
|
||||
/>
|
||||
<label className="form-check-label" htmlFor={outvar + variant}>
|
||||
{variant}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function MissingComponent(...args) {
|
||||
console.error("Missing component with args:", args)
|
||||
return <label style={{background: "red"}}>MISSING</label>
|
||||
}
|
||||
|
||||
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});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue