Add options for the cards #93
19
package.json
19
package.json
|
@ -16,18 +16,19 @@
|
||||||
"@babel/core": "^7.22.8",
|
"@babel/core": "^7.22.8",
|
||||||
"@babel/preset-env": "^7.22.7",
|
"@babel/preset-env": "^7.22.7",
|
||||||
"@babel/preset-react": "^7.22.5",
|
"@babel/preset-react": "^7.22.5",
|
||||||
"babel-preset-minify": "^0.5.2",
|
"axios": "^1.4.0",
|
||||||
"babel-loader": "^9.1.3",
|
"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": "^5.88.1",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
"bootstrap": "^5.3.0",
|
"json-logic-js": "^2.0.2",
|
||||||
"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",
|
|
||||||
"react-bootstrap": "^2.8.0"
|
"react-bootstrap": "^2.8.0"
|
||||||
},
|
},
|
||||||
"babel": {
|
"babel": {
|
||||||
|
|
|
@ -255,7 +255,7 @@ button {
|
||||||
|
|
||||||
.item-card-name,
|
.item-card-name,
|
||||||
.price {
|
.price {
|
||||||
> .alert-warning {
|
> .alert-warning, > .alert-info {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
height: inherit;
|
height: inherit;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
@ -382,7 +382,7 @@ button {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
/*max-width: 96px;*/
|
/*max-width: 96px;*/
|
||||||
max-width: 130px;
|
max-width: 132px;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -432,7 +432,7 @@ button {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .alert-warning {
|
> .alert-warning, > .alert-info {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
height: inherit;
|
height: inherit;
|
||||||
width: 20px;
|
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 {
|
.hovered {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { createRoot } from "react-dom/client";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import ProcessOptions from "./shop_components.jsx";
|
||||||
import { OverlayTrigger } from "react-bootstrap";
|
import { OverlayTrigger } from "react-bootstrap";
|
||||||
|
|
||||||
|
|
||||||
|
@ -593,7 +594,7 @@ class ProductCartItem extends React.PureComponent {
|
||||||
index,
|
index,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let warning;
|
let warning, options, options_data;
|
||||||
if (data && data.warnings) {
|
if (data && data.warnings) {
|
||||||
const warningsKeys = Object.keys(data.warnings);
|
const warningsKeys = Object.keys(data.warnings);
|
||||||
if (warningsKeys && warningsKeys.length > 0) {
|
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;
|
let render_progress;
|
||||||
if (data) {
|
if (data) {
|
||||||
switch(model.type) {
|
switch(model.type) {
|
||||||
|
@ -682,6 +692,34 @@ class ProductCartItem extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
</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>
|
<h6>{model.name_number}</h6>
|
||||||
|
|
||||||
|
@ -820,7 +858,9 @@ class Cart extends React.PureComponent {
|
||||||
let itemData;
|
let itemData;
|
||||||
if (data.itemsData && index in data.itemsData) {
|
if (data.itemsData && index in data.itemsData) {
|
||||||
itemData = data.itemsData[index];
|
itemData = data.itemsData[index];
|
||||||
|
console.log(itemData.options_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProductCartItem
|
<ProductCartItem
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
|
@ -1400,12 +1440,18 @@ class OrderSumary extends React.PureComponent {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{warning && (
|
{warning ? (
|
||||||
<img
|
<img
|
||||||
style={{'marginLeft': '10px'}}
|
style={{'marginLeft': '10px'}}
|
||||||
className="alert-warning"
|
className="alert-warning"
|
||||||
src={`/images/${warning.icon}`}
|
src={`/images/${warning.icon}`}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<img
|
||||||
|
style={{'marginLeft': '10px'}}
|
||||||
|
className="alert-warning"
|
||||||
|
src="/images/shop/icon-customize.svg"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!warning && (
|
{!warning && (
|
||||||
|
@ -1771,10 +1817,11 @@ class Shop extends React.PureComponent {
|
||||||
type: this.state.currentMode,
|
type: this.state.currentMode,
|
||||||
};
|
};
|
||||||
const clonedCart = Array.from(this.state.columns.cart.items);
|
const clonedCart = Array.from(this.state.columns.cart.items);
|
||||||
|
console.log(clonedCart);
|
||||||
for (const i in clonedCart) {
|
for (const i in clonedCart) {
|
||||||
const item = clonedCart[i];
|
const item = clonedCart[i];
|
||||||
crate.items.push({
|
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 itemsCloned = Array.from(newItems);
|
||||||
const itemsData = [];
|
const itemsData = [];
|
||||||
|
console.log(prevItems);
|
||||||
|
console.log(this.state);
|
||||||
const rules = {};
|
const rules = {};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2077,6 +2126,9 @@ class Shop extends React.PureComponent {
|
||||||
rules[ddkali.rules.follow.type] = {...ddkali.rules.follow};
|
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) {
|
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,
|
nbrCurrentClock: 0,
|
||||||
slotOccupied: 1,
|
slotOccupied: 1,
|
||||||
clockOccupied: 0,
|
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: {
|
rules: {
|
||||||
maxSlot: {
|
maxSlot: {
|
||||||
type: 'kasli-max-slot',
|
type: 'kasli-max-slot',
|
||||||
|
|
Loading…
Reference in New Issue