Add basic demo example

Kinda works, but buggy

Signed-off-by: Egor Savkin <es@m-labs.hk>
Egor Savkin 2023-08-17 14:42:47 +08:00
parent 212a7743eb
commit b8a293f34a
5 changed files with 174 additions and 18 deletions

View File

@ -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"
},
"babel": {
"presets": [

View File

@ -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;
@ -508,6 +508,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 {

View File

@ -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";
const data = window.shop_data;
@ -622,7 +623,7 @@ class ProductCartItem extends React.PureComponent {
shouldTooltipWarningClassInverted,
} = this.props;
let warning;
let warning, options, options_data;
if (data && data.warnings) {
const warningsKeys = Object.keys(data.warnings);
if (warningsKeys && warningsKeys.length > 0) {
@ -631,6 +632,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 (model.showProgress && data) {
switch(model.type) {
@ -699,9 +709,20 @@ class ProductCartItem extends React.PureComponent {
onMouseEnter={this.handleOnMouseEnterWarningItem.bind(this, index, warning)}
onMouseLeave={this.handleOnMouseLeaveWarningItem.bind(this, index, warning)}>
{warning && (
<img className="alert-warning" src={warning ? `/images${warning.icon}` : null} />
)}
{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': ''}`}>
@ -848,7 +869,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}
@ -1429,12 +1452,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 && (
@ -1833,10 +1862,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
});
}
@ -2040,6 +2070,8 @@ class Shop extends React.PureComponent {
const itemsCloned = Array.from(newItems);
const itemsData = [];
console.log(prevItems);
console.log(this.state);
const rules = {};
@ -2132,6 +2164,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) {

View File

@ -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});
}
}
}

View File

@ -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',