UNPKG

@fireflyai/backstage-plugin-firefly

Version:
167 lines (164 loc) 5.28 kB
import React from 'react'; import { Pie } from '@ant-design/plots'; import { InfoCard, EmptyState } from '@backstage/core-components'; import round from 'lodash/round'; import { useStyles, COLORS } from './IaCCoveragePieChart.styles.esm.js'; const IaCCoveragePieChart = ({ relatedEntities }) => { const classes = useStyles(); const hoveredType = "Unmanaged"; const statusesCounts = { Codified: 0, Unmanaged: 0, Ghost: 0, Drifted: 0, Undetermined: 0, "IaC-Ignored": 0, Child: 0, Pending: 0 }; relatedEntities.forEach((relatedEntity) => { if (relatedEntity?.metadata?.annotations?.["firefly.ai/asset-id"] === void 0) { return; } const lifecycle = relatedEntity?.spec?.lifecycle; switch (lifecycle) { case "managed": statusesCounts.Codified++; break; case "unmanaged": statusesCounts.Unmanaged++; break; case "ghost": statusesCounts.Ghost++; break; case "drifted": statusesCounts.Drifted++; break; case "undetermined": statusesCounts.Undetermined++; break; case "iacIgnored": statusesCounts["IaC-Ignored"]++; break; case "child": statusesCounts.Child++; break; case "pending": statusesCounts.Pending++; break; default: statusesCounts.Undetermined++; break; } }); const data = Object.entries(statusesCounts).map(([type, value]) => ({ type, value })); const total = data.reduce((sum, item) => sum + item.value, 0); const hoveredItem = data.find((item) => item.type === hoveredType); const hoveredPercentage = hoveredItem ? Math.round(hoveredItem.value / total * 100) : 0; const isZero = total === 0; const unmangedVal = data?.find((item) => item.type === "Unmanaged")?.value; const unmanagedPercent = unmangedVal ? round(unmangedVal / total * 100, 2).toFixed(0) : 0; if (isZero) { return /* @__PURE__ */ React.createElement(InfoCard, { title: "Resources IaC Coverage" }, /* @__PURE__ */ React.createElement( EmptyState, { missing: "data", title: "No Resource Dependencies Found", description: "This entity does not have any resource dependencies defined in the catalog." } )); } const handleEvents = (plot) => { plot.on("element:mouseenter", (event) => { const { value = 0, type = "" } = event?.data?.data || {}; const percentElement = document.getElementById("pieInfoPercent"); const infoElement = document.getElementById("pieInfo"); const descElement = document.getElementById("pieInfoDesc"); if (percentElement) { percentElement.textContent = `${round(value / total * 100, 2).toFixed(0)}% (${value})`; } if (infoElement) { infoElement.style.color = COLORS[type] || "#ccc"; } if (descElement) { descElement.textContent = type; } }); plot.on("element:mouseleave", () => { const percentElement = document.getElementById("pieInfoPercent"); const infoElement = document.getElementById("pieInfo"); const descElement = document.getElementById("pieInfoDesc"); if (percentElement) { percentElement.textContent = `${unmanagedPercent}% (${unmangedVal})`; } if (infoElement) { infoElement.style.color = COLORS.Unmanaged; } if (descElement) { descElement.textContent = "Unmanaged"; } }); }; const config = { appendPadding: 0, data, angleField: "value", colorField: "type", radius: 1, innerRadius: 0.8, tooltip: false, legend: false, label: { type: "spider", offset: "-50%", style: { textAlign: "center", fill: "rgba(255, 255, 255, 0)" }, position: "bottom", autoRotate: false }, color: (datum) => COLORS[datum.type] || "#C7C7C7", pieStyle: { lineWidth: 1, cursor: "pointer" }, statistic: { title: false, content: { style: { whiteSpace: "pre-wrap", overflow: "hidden", textOverflow: "ellipsis", padding: "10px 0" }, customHtml: () => { const element = /* @__PURE__ */ React.createElement( "div", { id: "pieInfo", style: { fontSize: 18, display: "flex", flexDirection: "column", gap: "5px", fontWeight: 300, color: COLORS[hoveredType] } }, /* @__PURE__ */ React.createElement("span", { id: "pieInfoPercent" }, hoveredPercentage, "% (", hoveredItem?.value, ")"), /* @__PURE__ */ React.createElement("span", { id: "pieInfoDesc" }, hoveredType) ); return element; } } }, onReady: handleEvents }; return /* @__PURE__ */ React.createElement(InfoCard, { title: "Resources IaC Coverage" }, /* @__PURE__ */ React.createElement("div", { className: classes.chartContainer }, /* @__PURE__ */ React.createElement(Pie, { ...config }))); }; export { IaCCoveragePieChart }; //# sourceMappingURL=IaCCoveragePieChart.esm.js.map