Refactor resource subsystem (still needs integration)

Signed-off-by: Egor Savkin <es@m-labs.hk>
pull/113/head
Egor Savkin 2023-12-01 17:36:55 +08:00
parent da3f18d6d9
commit e8b1d70356
5 changed files with 165 additions and 75 deletions

View File

@ -3,7 +3,8 @@ import PropTypes from "prop-types";
import {Draggable} from "@hello-pangea/dnd";
import {OverlayTrigger} from "react-bootstrap";
import {DialogPopup} from "./options/DialogPopup.jsx";
import {nbrClocksStyle, nbrConnectorsStyle, productStyle} from "./utils";
import {productStyle} from "./utils";
import {Resources} from "./Resources.jsx";
/**
* Component that renders a product.
@ -22,6 +23,7 @@ export class ProductCartItem extends PureComponent {
model: PropTypes.object.isRequired,
data: PropTypes.object,
ext_data: PropTypes.object,
resources: PropTypes.object,
onToggleOverlayRemove: PropTypes.func,
onClickRemoveItem: PropTypes.func,
onClickItem: PropTypes.func,
@ -79,6 +81,7 @@ export class ProductCartItem extends PureComponent {
first,
last,
ext_data,
resources,
onCardUpdate,
} = this.props;
@ -102,30 +105,7 @@ export class ProductCartItem extends PureComponent {
let render_progress;
if (data) {
switch(model.type) {
case 'kasli':
render_progress = [
(<p key={model.type+model.id+"EEM"}>{`${data.nbrCurrentSlot}/${model.nbrSlotMax} EEM connectors used`}</p>),
(<p key={model.type+model.id+"CLK"}>{`${data.nbrCurrentClock}/${model.nbrClockMax} Clock connectors used`}</p>)
];
break;
case 'vhdcicarrier':
render_progress = (<p>{`${data.nbrCurrentSlot}/${model.nbrSlotMax} EEM connectors used`}</p>);
break;
case 'zotino':
case 'hd68':
render_progress = (<p>{`${data.nbrCurrentSlot}/${model.nbrSlotMax} connectors used`}</p>);
break;
case 'clocker':
render_progress = (<p>{`${data.nbrCurrentClock}/${model.nbrClockMax} Clock connectors used`}</p>);
break;
default:
break;
}
}
return (
@ -218,28 +198,8 @@ export class ProductCartItem extends PureComponent {
</div>
{/* progression container */}
{render_progress && (
<OverlayTrigger
placement="top"
trigger={['click', 'hover', 'focus']}
overlay={({arrowProps, hasDoneInitialMeasure, show, ...props}) => (<div className="k-popup-connectors" {...props}>{render_progress}</div>)}
rootClose
>
<div className="progress-container">
{model.nbrSlotMax > 0 && (
<div className="nbr-connectors">
<div style={{ ...nbrConnectorsStyle(data)}}></div>
</div>
)}
{model.nbrClockMax > 0 && (
<div className="nbr-clocks">
<div style={{ ...nbrClocksStyle(data)}}></div>
</div>
)}
</div>
</OverlayTrigger>
{resources && (
<Resources resources={resources}/>
)}

View File

@ -0,0 +1,86 @@
import {OverlayTrigger} from "react-bootstrap";
import React from "react";
const resourcesWidthStyle = (occupied, max) => {
return {
width: `${Math.min(occupied * 100 / max, 100)}%`,
}
};
function EEMRenderer({occupied, max}) {
return (
<div className="nbr-connectors">
<div style={{...resourcesWidthStyle(occupied, max)}}></div>
</div>
)
}
function ClockRenderer({occupied, max}) {
return (
<div className="nbr-clocks">
<div style={{...resourcesWidthStyle(occupied, max)}}></div>
</div>
)
}
const resource_progress_renderers = {
"eem": EEMRenderer,
"clk": ClockRenderer,
"idc": EEMRenderer
}
function EEMTipRender({occupied, max}) {
return (<p>{`${occupied}/${max} EEM connectors used`}</p>);
}
function IDCTipRender({occupied, max}) {
return (<p>{`${occupied}/${max} IDC connectors used`}</p>);
}
function ClockTipRender({occupied, max}) {
return (<p>{`${occupied}/${max} clock connectors used`}</p>);
}
const resource_tip = {
"eem": EEMTipRender,
"clk": ClockTipRender,
"idc": IDCTipRender
}
function RenderResources({resources, library}) {
if (!resources) return null;
let result = [];
resources.forEach((value, _) => {
if (library[value.name]) result.push(library[value.name](value));
});
return result;
}
export function Resources({resources}) {
return (
<OverlayTrigger
placement="top"
trigger={['click', 'hover', 'focus']}
overlay={({arrowProps, hasDoneInitialMeasure, show, ...props}) => (
<div className="k-popup-connectors" {...props}>
<RenderResources
resources={resources}
library={resource_tip}
/>
</div>
)}
rootClose
>
<div className="progress-container">
<RenderResources
resources={resources}
library={resource_progress_renderers}
/>
</div>
</OverlayTrigger>
)
}

View File

@ -0,0 +1,67 @@
function EEMCounter(data, index) {
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 || 0;
}
let count = 0;
for (let i = index + 1; i < data.length; i++) {
if (data[i].resources.filter((value, _i) => value.name === "eem").length > 0) break;
count += process_slots(data[i]);
}
return count;
}
function ClockCounter(data, index) {
const process_slots = (item) => {
return (item.options_data && item.options_data.ext_clk === true) ? 0 : (item.clockOccupied || 0);
}
let count = 0;
for (let i = index + 1; i < data.length; i++) {
if (data[i].resources.filter((value, _i) => value.name === "clk").length > 0) break;
count += process_slots(data[i]);
}
return count;
}
function IDCCounter(data, index) {
const process_slots = (item) => {
return item.idcOccupied || 0;
}
let count = 0;
for (let i = index + 1; i < data.length; i++) {
if (data[i].resources.filter((value, _i) => value.name === "idc").length > 0) break;
count += process_slots(data[i]);
}
return count;
}
const resource_counters = {
"eem": EEMCounter,
"clk": ClockCounter,
"idc": IDCCounter
}
export function CountResources(data, index) {
if (!data[index].resources) return null;
let result = [];
data[index].resources.forEach((item, _) => {
if (resource_counters[item.name]) result.push({
name: item.name,
occupied: resource_counters[item.name](data, index),
max: item.max
});
});
return result;
}

View File

@ -76,35 +76,6 @@ export const cartStyle = (style, snapshot) => {
};
}
export const nbrConnectorsStyle = (data) => {
if (!data || !data.nbrCurrentSlot) {
return {};
}
let p = data.nbrCurrentSlot * 100 / data.nbrSlotMax;
if (p > 100) {
p = 100;
}
return {
width: `${p}%`,
}
};
export const nbrClocksStyle = (data) => {
if (!data || !data.nbrCurrentClock) {
return {};
}
let p = data.nbrCurrentClock * 100 / data.nbrClockMax;
if (p > 100) {
p = 100;
}
return {
width: `${p}%`,
}
};
export const nbrOccupiedSlotsInCrate = (items) => {
return items.reduce((prev, next) => {

View File

@ -0,0 +1,6 @@
/**
* This module should contain warnings subsystem.
* First idea - there should be either definitive list of available warnings,
* or defined as some json logic leading to the warning message(s), similar way how FillExtData works.
* Second - resources indicator should be separate component
*/