Visual Console Refactor: huge improvements into the percentile item

Former-commit-id: 4ec68e2966b1fa97456c78807391e9cc68c6355b
This commit is contained in:
Alejandro Gallardo Escobar 2019-04-04 18:24:39 +02:00
parent 0d46d0a1a0
commit 92428f3731
2 changed files with 182 additions and 16 deletions

View File

@ -229,6 +229,58 @@
processValue: "none"
};
var percentileRawProps = {
// Generic props.
id: 10,
type: 3, // Percentile = 3
label: null,
isLinkEnabled: false,
isOnTop: false,
parentId: null,
aclGroupId: null,
// Position props.
x: 790,
y: 10,
// Size props.
width: 200,
height: 40,
// Custom props.
percentileType: "progress-bar",
valueType: "percent",
minValue: 100,
maxValue: 500,
color: null,
labelColor: "#82B92E",
value: 245,
unit: "seconds"
};
var percentileBubbleRawProps = {
// Generic props.
id: 11,
type: 3, // Percentile = 3
label: null,
isLinkEnabled: false,
isOnTop: false,
parentId: null,
aclGroupId: null,
// Position props.
x: 830,
y: 60,
// Size props.
width: 100,
height: 100,
// Custom props.
percentileType: "bubble",
valueType: "value",
minValue: 100,
maxValue: 500,
color: null,
labelColor: "#82B92E",
value: 245,
unit: "seconds"
};
var items = [
staticGraphRawProps,
colorCloudRawProps,
@ -238,7 +290,9 @@
boxRawProps,
lineRawProps,
labelRawProps,
simpleValueRawProps
simpleValueRawProps,
percentileRawProps,
percentileBubbleRawProps
];
try {

View File

@ -6,9 +6,9 @@ import {
import {
linkedVCPropsDecoder,
modulePropsDecoder,
decodeBase64,
stringIsEmpty,
notEmptyStringOr
notEmptyStringOr,
parseIntOr,
parseFloatOr
} from "../lib";
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
@ -20,10 +20,12 @@ export type PercentileProps = {
| "circular-progress-bar"
| "circular-progress-bar-alt";
valueType: "percent" | "value";
value: string | null;
minValue: number | null;
maxValue: number | null;
color: string | null;
labelColor: string | null;
html: string;
value: number | null;
unit: string | null;
} & ItemProps &
WithModuleProps &
LinkedVisualConsoleProps;
@ -79,31 +81,141 @@ function extractValueType(valueType: any): PercentileProps["valueType"] {
export function percentilePropsDecoder(
data: UnknownObject
): PercentileProps | never {
if (stringIsEmpty(data.html) || stringIsEmpty(data.encodedHtml)) {
throw new TypeError("missing html content.");
}
return {
...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
type: ItemType.PERCENTILE_BAR,
percentileType: extractPercentileType(data.type),
percentileType: extractPercentileType(data.percentileType || data.type),
valueType: extractValueType(data.valueType),
value: notEmptyStringOr(data.value, null),
minValue: parseIntOr(data.minValue, null),
maxValue: parseIntOr(data.maxValue, null),
color: notEmptyStringOr(data.color, null),
labelColor: notEmptyStringOr(data.labelColor, null),
html: !stringIsEmpty(data.html)
? data.html
: decodeBase64(data.encodedHtml),
value: parseFloatOr(data.value, null),
unit: notEmptyStringOr(data.unit, null),
...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
};
}
const svgNS = "http://www.w3.org/2000/svg";
export default class Percentile extends Item<PercentileProps> {
public createDomElement(): HTMLElement {
// Progress.
const progress = this.getProgress();
// Display value.
let displayValue: string;
if (this.props.valueType === "value") {
displayValue = this.props.unit
? `${this.props.value} ${this.props.unit}`
: `${this.props.value}`;
} else {
displayValue = `${progress}%`;
}
// Main element.
const element = document.createElement("div");
element.innerHTML = this.props.html;
// SVG container.
const svg = document.createElementNS(svgNS, "svg");
switch (this.props.percentileType) {
case "progress-bar":
{
const backgroundRect = document.createElementNS(svgNS, "rect");
backgroundRect.setAttribute("fill", "#000000");
backgroundRect.setAttribute("fill-opacity", "0.5");
backgroundRect.setAttribute("width", "100");
backgroundRect.setAttribute("height", "20");
backgroundRect.setAttribute("rx", "5");
backgroundRect.setAttribute("ry", "5");
const progressRect = document.createElementNS(svgNS, "rect");
progressRect.setAttribute("fill", this.props.color || "#F0F0F0");
progressRect.setAttribute("fill-opacity", "1");
progressRect.setAttribute("width", `${progress}`);
progressRect.setAttribute("height", "20");
progressRect.setAttribute("rx", "5");
progressRect.setAttribute("ry", "5");
const text = document.createElementNS(svgNS, "text");
text.setAttribute("text-anchor", "middle");
text.setAttribute("alignment-baseline", "middle");
text.setAttribute("font-size", "12");
text.setAttribute("font-family", "arial");
text.setAttribute("font-weight", "bold");
text.setAttribute("transform", "translate(50 11)");
text.setAttribute("fill", this.props.labelColor || "#FFFFFF");
if (this.props.valueType === "value") {
text.textContent = this.props.unit
? `${this.props.value} ${this.props.unit}`
: `${this.props.value}`;
} else {
text.textContent = `${progress}%`;
}
// Auto resize SVG using the view box magic: https://css-tricks.com/scale-svg/
svg.setAttribute("viewBox", "0 0 100 20");
svg.append(backgroundRect, progressRect, text);
}
break;
case "bubble":
case "circular-progress-bar": // TODO: Add this chart.
case "circular-progress-bar-alt": // TODO: Add this chart.
{
const backgroundCircle = document.createElementNS(svgNS, "circle");
backgroundCircle.setAttribute("transform", "translate(50 50)");
backgroundCircle.setAttribute("fill", "#000000");
backgroundCircle.setAttribute("fill-opacity", "0.5");
backgroundCircle.setAttribute("r", "50");
const progressCircle = document.createElementNS(svgNS, "circle");
progressCircle.setAttribute("transform", "translate(50 50)");
progressCircle.setAttribute("fill", this.props.color || "#F0F0F0");
progressCircle.setAttribute("fill-opacity", "1");
progressCircle.setAttribute("r", `${progress / 2}`);
const text = document.createElementNS(svgNS, "text");
text.setAttribute("text-anchor", "middle");
text.setAttribute("alignment-baseline", "middle");
text.setAttribute("font-size", "16");
text.setAttribute("font-family", "arial");
text.setAttribute("font-weight", "bold");
text.setAttribute("transform", "translate(50 32)");
text.setAttribute("fill", this.props.labelColor || "#FFFFFF");
if (this.props.valueType === "value") {
const value = document.createElementNS(svgNS, "tspan");
value.setAttribute("x", "0");
value.setAttribute("dy", "1em");
value.textContent = `${this.props.value}`;
const unit = document.createElementNS(svgNS, "tspan");
unit.setAttribute("x", "0");
unit.setAttribute("dy", "1em");
if (this.props.unit) {
unit.textContent = `${this.props.unit}`;
}
text.append(value, unit);
} else {
text.textContent = `${progress}%`;
}
// Auto resize SVG using the view box magic: https://css-tricks.com/scale-svg/
svg.setAttribute("viewBox", "0 0 100 100");
svg.append(backgroundCircle, progressCircle, text);
}
break;
}
element.append(svg);
return element;
}
private getProgress(): number {
const minValue = this.props.minValue || 0;
const maxValue = this.props.maxValue || 100;
const value = this.props.value || 100;
if (value <= minValue) return 0;
else if (value >= maxValue) return 100;
else return ((value - minValue) / (maxValue - minValue)) * 100;
}
}