web-mojo 2.1.530 → 2.1.531
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.es.js +10 -10
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.cjs.js.map +1 -1
- package/dist/auth.es.js +3 -3
- package/dist/auth.es.js.map +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.cjs.js.map +1 -1
- package/dist/charts.es.js +33 -3
- package/dist/charts.es.js.map +1 -1
- package/dist/chunks/{ChatView-3bLrmaJW.js → ChatView-BwazIhTw.js} +6 -6
- package/dist/chunks/{ChatView-3bLrmaJW.js.map → ChatView-BwazIhTw.js.map} +1 -1
- package/dist/chunks/{ChatView-QIVFlXuj.js → ChatView-siPKtjEy.js} +2 -2
- package/dist/chunks/{ChatView-QIVFlXuj.js.map → ChatView-siPKtjEy.js.map} +1 -1
- package/dist/chunks/{ContextMenu-BIGoLY_o.js → ContextMenu-BJlCv6JA.js} +2 -2
- package/dist/chunks/{ContextMenu-BIGoLY_o.js.map → ContextMenu-BJlCv6JA.js.map} +1 -1
- package/dist/chunks/{ContextMenu-e3pyiiOa.js → ContextMenu-DmPpGvRg.js} +2 -2
- package/dist/chunks/{ContextMenu-e3pyiiOa.js.map → ContextMenu-DmPpGvRg.js.map} +1 -1
- package/dist/chunks/{DataView-CyJP6CQe.js → DataView-DIJNkBzQ.js} +2 -2
- package/dist/chunks/{DataView-CyJP6CQe.js.map → DataView-DIJNkBzQ.js.map} +1 -1
- package/dist/chunks/{DataView-CyFedYm0.js → DataView-DohifQcG.js} +2 -2
- package/dist/chunks/{DataView-CyFedYm0.js.map → DataView-DohifQcG.js.map} +1 -1
- package/dist/chunks/{Dialog-CnRfQTYa.js → Dialog-CcCWITnV.js} +2 -2
- package/dist/chunks/{Dialog-CnRfQTYa.js.map → Dialog-CcCWITnV.js.map} +1 -1
- package/dist/chunks/{Dialog-Bapv9rkO.js → Dialog-CqJQlXoj.js} +5 -5
- package/dist/chunks/{Dialog-Bapv9rkO.js.map → Dialog-CqJQlXoj.js.map} +1 -1
- package/dist/chunks/{FormView-DnQnTK4i.js → FormView-CMdyHmf3.js} +2 -2
- package/dist/chunks/{FormView-DnQnTK4i.js.map → FormView-CMdyHmf3.js.map} +1 -1
- package/dist/chunks/{FormView-zxpjefn-.js → FormView-zxAz97lg.js} +2 -2
- package/dist/chunks/{FormView-zxpjefn-.js.map → FormView-zxAz97lg.js.map} +1 -1
- package/dist/chunks/{MetricsChart-D9BbM9XI.js → MetricsChart-Bbn-L_9C.js} +3 -3
- package/dist/chunks/{MetricsChart-D9BbM9XI.js.map → MetricsChart-Bbn-L_9C.js.map} +1 -1
- package/dist/chunks/{MetricsChart-CQ623_mm.js → MetricsChart-BfeD0WY-.js} +2 -2
- package/dist/chunks/{MetricsChart-CQ623_mm.js.map → MetricsChart-BfeD0WY-.js.map} +1 -1
- package/dist/chunks/{PDFViewer-C-7ad1k4.js → PDFViewer-BUAS2Hkr.js} +3 -3
- package/dist/chunks/{PDFViewer-C-7ad1k4.js.map → PDFViewer-BUAS2Hkr.js.map} +1 -1
- package/dist/chunks/{PDFViewer-stA6i3Pg.js → PDFViewer-DQvqJVD2.js} +2 -2
- package/dist/chunks/{PDFViewer-stA6i3Pg.js.map → PDFViewer-DQvqJVD2.js.map} +1 -1
- package/dist/chunks/{Page-BXOlm35J.js → Page-BZA8Inm2.js} +2 -2
- package/dist/chunks/{Page-BXOlm35J.js.map → Page-BZA8Inm2.js.map} +1 -1
- package/dist/chunks/{Page-BnascB9g.js → Page-BvVfjiCv.js} +2 -2
- package/dist/chunks/{Page-BnascB9g.js.map → Page-BvVfjiCv.js.map} +1 -1
- package/dist/chunks/{TopNav-B78TIsE2.js → TopNav-BjPDz8n_.js} +2 -2
- package/dist/chunks/{TopNav-B78TIsE2.js.map → TopNav-BjPDz8n_.js.map} +1 -1
- package/dist/chunks/{TopNav-Dk9TI5MO.js → TopNav-ChmlxQ5s.js} +2 -2
- package/dist/chunks/{TopNav-Dk9TI5MO.js.map → TopNav-ChmlxQ5s.js.map} +1 -1
- package/dist/chunks/{WebApp-B-8rGWlA.js → WebApp-KZbQxSrZ.js} +2 -2
- package/dist/chunks/{WebApp-B-8rGWlA.js.map → WebApp-KZbQxSrZ.js.map} +1 -1
- package/dist/chunks/{WebApp-Bnpizp35.js → WebApp-zyQ4x8MK.js} +13 -13
- package/dist/chunks/{WebApp-Bnpizp35.js.map → WebApp-zyQ4x8MK.js.map} +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +5 -5
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +11 -11
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +4 -4
- package/package.json +1 -1
package/dist/charts.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./chunks/MetricsChart-CQ623_mm.js"),e=require("./chunks/WebApp-B-8rGWlA.js");class MiniChart extends e.View{constructor(t={}){super({className:"mini-chart",...t}),this.chartType=t.chartType||"line",this.data=t.data||[],this.width=t.width||"100%",this.height=t.height||30,this.maintainAspectRatio=t.maintainAspectRatio||!1,this.color=t.color||"rgba(54, 162, 235, 1)",this.fillColor=t.fillColor||"rgba(54, 162, 235, 0.1)",this.strokeWidth=t.strokeWidth||2,this.barGap=t.barGap||2,this.fill=!1!==t.fill,this.smoothing=t.smoothing||.3,this.padding=t.padding||2,this.minValue=t.minValue,this.maxValue=t.maxValue,this.showDots=t.showDots||!1,this.dotRadius=t.dotRadius||2,this.animate=!1!==t.animate,this.animationDuration=t.animationDuration||300,this.showTooltip=!1!==t.showTooltip,this.tooltipFormatter=t.tooltipFormatter||null,this.showCrosshair=!1!==t.showCrosshair,this.crosshairColor=t.crosshairColor||"rgba(0, 0, 0, 0.2)",this.crosshairWidth=t.crosshairWidth||1,this.tooltip=null,this.crosshair=null,this.hoveredIndex=-1}getTemplate(){const t="number"==typeof this.width?`${this.width}px`:this.width,e="number"==typeof this.height?`${this.height}px`:this.height,s=this.maintainAspectRatio?"xMidYMid meet":"none";return`\n <div class="mini-chart-wrapper" style="position: relative; display: block; width: ${t}; height: ${e};">\n <svg \n class="mini-chart-svg" \n width="100%" \n height="100%"\n viewBox="0 0 100 ${this.height}"\n preserveAspectRatio="${s}"\n style="display: block;">\n </svg>\n ${this.showTooltip?'<div class="mini-chart-tooltip" style="display: none;"></div>':""}\n </div>\n `}async onAfterRender(){this.svg=this.element.querySelector(".mini-chart-svg"),this.tooltip=this.element.querySelector(".mini-chart-tooltip"),this.updateDimensions(),this.data&&this.data.length>0&&this.renderChart(),this.showTooltip&&this.svg&&this.setupTooltip(),this.setupResizeObserver()}updateDimensions(){if(!this.svg)return;const t=this.svg.getBoundingClientRect();this.actualWidth=t.width||100,this.actualHeight=t.height||this.height,this.svg.setAttribute("viewBox",`0 0 ${this.actualWidth} ${this.actualHeight}`)}setupResizeObserver(){"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(()=>{this.updateDimensions(),this.data&&this.data.length>0&&this.renderChart()}),this.svg&&this.resizeObserver.observe(this.svg))}renderChart(){if(!this.svg||!this.data||0===this.data.length)return;this.svg.innerHTML="";const{min:t,max:e}=this.calculateBounds();if("line"===this.chartType?this.renderLine(t,e):"bar"===this.chartType&&this.renderBar(t,e),this.showCrosshair){const t=this.getActualHeight();this.crosshair=this.createSVGElement("line",{x1:0,y1:0,x2:0,y2:t,stroke:this.crosshairColor,"stroke-width":this.crosshairWidth,"stroke-dasharray":"3,3",style:"display: none; pointer-events: none;"}),this.svg.appendChild(this.crosshair)}this.showTooltip&&this.tooltip&&this.setupTooltip(),this.animate&&this.applyAnimation()}calculateBounds(){const t=this.data.map(t=>"object"==typeof t?t.value:t);let e=void 0!==this.minValue?this.minValue:Math.min(...t),s=void 0!==this.maxValue?this.maxValue:Math.max(...t);return 0===s-e&&(e-=1,s+=1),{min:e,max:s}}getActualWidth(){return this.actualWidth||this.width||100}getActualHeight(){return this.actualHeight||this.height||30}renderLine(t,e){const s=this.data.map(t=>"object"==typeof t?t.value:t),i=this.calculatePoints(s,t,e);if(this.fill){const t=this.createAreaPath(i),e=this.createSVGElement("path",{d:t,fill:this.fillColor,stroke:"none"});this.svg.appendChild(e)}const h=this.smoothing>0?this.createSmoothPath(i):this.createLinePath(i),r=this.createSVGElement("path",{d:h,fill:"none",stroke:this.color,"stroke-width":this.strokeWidth,"stroke-linecap":"round","stroke-linejoin":"round"});this.svg.appendChild(r),this.showDots&&i.forEach(t=>{const e=this.createSVGElement("circle",{cx:t.x,cy:t.y,r:this.dotRadius,fill:this.color});this.svg.appendChild(e)})}renderBar(t,e){const s=this.data.map(t=>"object"==typeof t?t.value:t),i=this.calculatePoints(s,t,e),h=this.getActualWidth(),r=this.getActualHeight(),a=(h-2*this.padding-this.barGap*(s.length-1))/s.length;i.forEach((t,e)=>{const s=r-2*this.padding-t.y+this.padding,i=t.x-a/2,h=t.y,o=this.createSVGElement("rect",{x:i,y:h,width:a,height:s,fill:this.color,rx:1,"data-bar-index":e,class:"mini-chart-bar"});this.svg.appendChild(o)})}calculatePoints(t,e,s){const i=s-e,h=this.getActualWidth(),r=this.getActualHeight(),a=(h-2*this.padding)/(t.length-1||1),o=(r-2*this.padding)/i;return t.map((t,s)=>({x:this.padding+s*a,y:r-this.padding-(t-e)*o}))}createLinePath(t){if(0===t.length)return"";let e=`M ${t[0].x},${t[0].y}`;for(let s=1;s<t.length;s++)e+=` L ${t[s].x},${t[s].y}`;return e}createSmoothPath(t){if(t.length<2)return this.createLinePath(t);let e=`M ${t[0].x},${t[0].y}`;for(let s=0;s<t.length-1;s++){const i=t[s],h=t[s+1];e+=` C ${i.x+(h.x-i.x)*this.smoothing},${i.y} ${h.x-(h.x-i.x)*this.smoothing},${h.y} ${h.x},${h.y}`}return e}createAreaPath(t){if(0===t.length)return"";const e=this.smoothing>0?this.createSmoothPath(t):this.createLinePath(t),s=t[t.length-1],i=t[0],h=this.getActualHeight();return`${e} L ${s.x},${h-this.padding} L ${i.x},${h-this.padding} Z`}createSVGElement(t,e={}){const s=document.createElementNS("http://www.w3.org/2000/svg",t);return Object.entries(e).forEach(([t,e])=>{s.setAttribute(t,e)}),s}applyAnimation(){this.svg.querySelectorAll("path").forEach(t=>{const e=t.getTotalLength();t.style.strokeDasharray=e,t.style.strokeDashoffset=e,t.style.animation=`mini-chart-draw ${this.animationDuration}ms ease-out forwards`}),this.svg.querySelectorAll("rect").forEach((t,e)=>{t.style.transformOrigin="bottom",t.style.animation=`mini-chart-bar-grow ${this.animationDuration}ms ease-out ${20*e}ms forwards`,t.style.transform="scaleY(0)"})}setupTooltip(){if(!this.svg||!this.tooltip)return;const t=this.data.map(t=>"object"==typeof t?t.value:t),e=this.calculatePoints(t,...Object.values(this.calculateBounds())),s=this.getActualWidth(),i=this.getActualHeight(),h=s/t.length;e.forEach((t,e)=>{const s=this.createSVGElement("rect",{x:e*h,y:0,width:h,height:i,fill:"transparent",style:"cursor: pointer;"});s.addEventListener("mouseenter",t=>{this.showTooltipAtIndex(e,t)}),s.addEventListener("mousemove",t=>{this.updateTooltipPosition(t)}),s.addEventListener("mouseleave",()=>{this.hideTooltip()}),this.svg.appendChild(s)})}showTooltipAtIndex(t,e){if(!this.tooltip)return;this.hoveredIndex=t;const s="object"==typeof this.data[t]?this.data[t].value:this.data[t],i="object"==typeof this.data[t]?this.data[t].label:null;let h=s;this.tooltipFormatter?"function"==typeof this.tooltipFormatter&&(h=this.tooltipFormatter(s,t)):h="number"==typeof s?s.toLocaleString():s;let r=`<strong>${h}</strong>`;if(i&&(r=`${i}<br>${r}`),this.tooltip.innerHTML=r,this.tooltip.style.display="block",this.updateTooltipPosition(e),"bar"===this.chartType&&this.highlightBar(t),this.crosshair&&this.showCrosshair){const e=this.getActualWidth()/this.data.length,s=t*e+e/2;this.crosshair.setAttribute("x1",s),this.crosshair.setAttribute("x2",s),this.crosshair.style.display="block"}}updateTooltipPosition(t){if(!this.tooltip||"none"===this.tooltip.style.display)return;const e=this.svg.getBoundingClientRect(),s=t.clientX-e.left,i=t.clientY-e.top;this.tooltip.style.left=`${s}px`,this.tooltip.style.top=i-10+"px",this.tooltip.style.transform="translate(-50%, -100%)"}hideTooltip(){this.tooltip&&(this.tooltip.style.display="none",this.hoveredIndex=-1),"bar"===this.chartType&&this.unhighlightBars(),this.crosshair&&(this.crosshair.style.display="none")}highlightBar(t){if(!this.svg)return;this.unhighlightBars();const e=this.svg.querySelector(`rect.mini-chart-bar[data-bar-index="${t}"]`);e&&(e.style.opacity="0.7")}unhighlightBars(){this.svg&&this.svg.querySelectorAll("rect.mini-chart-bar").forEach(t=>{t.style.opacity="1"})}setData(t){this.data=t,this.svg&&this.renderChart()}setColor(t){this.color=t,this.svg&&this.renderChart()}setType(t){["line","bar"].includes(t)&&(this.chartType=t,this.svg&&this.renderChart())}resize(t,e){this.width=t,this.height=e,this.updateDimensions(),this.svg&&this.renderChart()}async onBeforeDestroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),await super.onBeforeDestroy()}}exports.BaseChart=t.BaseChart,exports.MetricsChart=t.MetricsChart,exports.PieChart=t.PieChart,exports.SeriesChart=t.SeriesChart,exports.BUILD_TIME=e.BUILD_TIME,exports.VERSION=e.VERSION,exports.VERSION_INFO=e.VERSION_INFO,exports.VERSION_MAJOR=e.VERSION_MAJOR,exports.VERSION_MINOR=e.VERSION_MINOR,exports.VERSION_REVISION=e.VERSION_REVISION,exports.WebApp=e.WebApp,exports.MetricsMiniChart=class extends MiniChart{constructor(t={}){super(t),this.endpoint=t.endpoint||"/api/metrics/fetch",this.account=t.account||"global",this.granularity=t.granularity||"hours",this.slugs=t.slugs||null,this.category=t.category||null,this.dateStart=t.dateStart||null,this.dateEnd=t.dateEnd||null,this.defaultDateRange=t.defaultDateRange||"24h",this.isLoading=!1,this.lastFetch=null,this.refreshInterval=t.refreshInterval,this.dateStart&&this.dateEnd||this.setQuickRange(this.defaultDateRange),this.slugs&&!Array.isArray(this.slugs)&&(this.slugs=[this.slugs])}async onAfterRender(){await super.onAfterRender(),!this.endpoint||this.data&&0!==this.data.length||await this.fetchData(),this.refreshInterval&&this.endpoint&&this.startAutoRefresh()}buildApiParams(){const t={granularity:this.granularity,account:this.account,with_labels:!0};return this.slugs&&this.slugs.length>0&&this.slugs.forEach(e=>{t["slugs[]"]||(t["slugs[]"]=[]),t["slugs[]"].push(e)}),this.category&&(t.category=this.category),this.dateStart&&(t.dr_start=Math.floor(this.dateStart.getTime()/1e3)),this.dateEnd&&(t.dr_end=Math.floor(this.dateEnd.getTime()/1e3)),t._=Date.now(),t}async fetchData(){if(this.endpoint){this.isLoading=!0;try{const t=this.getApp()?.rest;if(!t)throw new Error("No REST client available");const e=this.buildApiParams(),s=await t.GET(this.endpoint,e);if(!s.success)throw new Error(s.message||"Network error");if(!s.data?.status)throw new Error(s.data?.error||"Server error");const i=s.data.data;this.processMetricsData(i),this.lastFetch=/* @__PURE__ */new Date,await this.render(),this.emit("metrics:loaded",{chart:this,data:i,params:e})}catch(t){console.error("Failed to fetch metrics:",t),this.emit("metrics:error",{chart:this,error:t})}finally{this.isLoading=!1}}}processMetricsData(t){const{data:e,labels:s}=t;if(!e)return;const i=Object.keys(e);if(0===i.length)return;const h=e[i[0]].map(t=>null==t||""===t?0:"number"==typeof t?t:parseFloat(t)||0);this.setData(h)}setQuickRange(t){const e=/* @__PURE__ */new Date;let s;switch(t){case"1h":s=new Date(e.getTime()-36e5);break;case"24h":default:s=new Date(e.getTime()-864e5);break;case"7d":s=new Date(e.getTime()-6048e5);break;case"30d":s=new Date(e.getTime()-2592e6)}this.dateStart=s,this.dateEnd=e}startAutoRefresh(){this.refreshTimer&&clearInterval(this.refreshTimer),this.refreshTimer=setInterval(()=>{this.fetchData()},this.refreshInterval)}stopAutoRefresh(){this.refreshTimer&&(clearInterval(this.refreshTimer),this.refreshTimer=null)}setGranularity(t){return this.granularity=t,this.fetchData()}setDateRange(t,e){return this.dateStart=new Date(t),this.dateEnd=new Date(e),this.fetchData()}setMetrics(t){return this.slugs=Array.isArray(t)?t:[t],this.fetchData()}refresh(){return this.fetchData()}async onBeforeDestroy(){this.stopAutoRefresh(),await super.onBeforeDestroy()}},exports.MiniChart=MiniChart;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./chunks/MetricsChart-BfeD0WY-.js"),s=require("./chunks/WebApp-KZbQxSrZ.js");class MiniChart extends s.View{constructor(t={}){super({className:"mini-chart",...t}),this.chartType=t.chartType||"line",this.data=t.data||[],this.width=t.width||"100%",this.height=t.height||30,this.maintainAspectRatio=t.maintainAspectRatio||!1,this.color=t.color||"rgba(54, 162, 235, 1)",this.fillColor=t.fillColor||"rgba(54, 162, 235, 0.1)",this.strokeWidth=t.strokeWidth||2,this.barGap=t.barGap||2,this.fill=!1!==t.fill,this.smoothing=t.smoothing||.3,this.padding=t.padding||2,this.minValue=t.minValue,this.maxValue=t.maxValue,this.showDots=t.showDots||!1,this.dotRadius=t.dotRadius||2,this.animate=!1!==t.animate,this.animationDuration=t.animationDuration||300,this.showTooltip=!1!==t.showTooltip,this.tooltipFormatter=t.tooltipFormatter||null,this.showCrosshair=!1!==t.showCrosshair,this.crosshairColor=t.crosshairColor||"rgba(0, 0, 0, 0.2)",this.crosshairWidth=t.crosshairWidth||1,this.showXAxis=t.showXAxis||!1,this.xAxisColor=t.xAxisColor||this.color,this.xAxisWidth=t.xAxisWidth||1,this.xAxisDashed=!1!==t.xAxisDashed,this.tooltip=null,this.crosshair=null,this.hoveredIndex=-1}getTemplate(){const t="number"==typeof this.width?`${this.width}px`:this.width,s="number"==typeof this.height?`${this.height}px`:this.height,e=this.maintainAspectRatio?"xMidYMid meet":"none";return`\n <div class="mini-chart-wrapper" style="position: relative; display: block; width: ${t}; height: ${s};">\n <svg \n class="mini-chart-svg" \n width="100%" \n height="100%"\n viewBox="0 0 100 ${this.height}"\n preserveAspectRatio="${e}"\n style="display: block;">\n </svg>\n ${this.showTooltip?'<div class="mini-chart-tooltip" style="display: none;"></div>':""}\n </div>\n `}async onAfterRender(){this.svg=this.element.querySelector(".mini-chart-svg"),this.tooltip=this.element.querySelector(".mini-chart-tooltip"),this.updateDimensions(),this.data&&this.data.length>0&&this.renderChart(),this.showTooltip&&this.svg&&this.setupTooltip(),this.setupResizeObserver()}updateDimensions(){if(!this.svg)return;const t=this.svg.getBoundingClientRect();this.actualWidth=t.width||100,this.actualHeight=t.height||this.height,this.svg.setAttribute("viewBox",`0 0 ${this.actualWidth} ${this.actualHeight}`)}setupResizeObserver(){"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(()=>{this.updateDimensions(),this.data&&this.data.length>0&&this.renderChart()}),this.svg&&this.resizeObserver.observe(this.svg))}renderChart(){if(!this.svg||!this.data||0===this.data.length)return;this.svg.innerHTML="";const{min:t,max:s}=this.calculateBounds();if(this.showXAxis&&this.renderXAxis(t,s),"line"===this.chartType?this.renderLine(t,s):"bar"===this.chartType&&this.renderBar(t,s),this.showCrosshair){const t=this.getActualHeight();this.crosshair=this.createSVGElement("line",{x1:0,y1:0,x2:0,y2:t,stroke:this.crosshairColor,"stroke-width":this.crosshairWidth,"stroke-dasharray":"3,3",style:"display: none; pointer-events: none;"}),this.svg.appendChild(this.crosshair)}this.showTooltip&&this.tooltip&&this.setupTooltip(),this.animate&&this.applyAnimation()}renderXAxis(t,s){const e=this.getActualWidth(),i=this.getActualHeight();let h;if(t<=0&&s>=0){const e=s-t,a=(i-2*this.padding)/e;h=i-this.padding-(0-t)*a}else h=i-this.padding;const a=this.createSVGElement("line",{x1:this.padding,y1:h,x2:e-this.padding,y2:h,stroke:this.xAxisColor,"stroke-width":this.xAxisWidth,"stroke-dasharray":this.xAxisDashed?"2,2":"none","stroke-opacity":"0.5"});this.svg.appendChild(a)}calculateBounds(){const t=this.data.map(t=>"object"==typeof t?t.value:t);let s=void 0!==this.minValue?this.minValue:Math.min(...t),e=void 0!==this.maxValue?this.maxValue:Math.max(...t);return 0===e-s&&(s-=1,e+=1),{min:s,max:e}}getActualWidth(){return this.actualWidth||this.width||100}getActualHeight(){return this.actualHeight||this.height||30}renderLine(t,s){const e=this.data.map(t=>"object"==typeof t?t.value:t),i=this.calculatePoints(e,t,s);if(this.fill){const t=this.createAreaPath(i),s=this.createSVGElement("path",{d:t,fill:this.fillColor,stroke:"none"});this.svg.appendChild(s)}const h=this.smoothing>0?this.createSmoothPath(i):this.createLinePath(i),a=this.createSVGElement("path",{d:h,fill:"none",stroke:this.color,"stroke-width":this.strokeWidth,"stroke-linecap":"round","stroke-linejoin":"round"});this.svg.appendChild(a),this.showDots&&i.forEach(t=>{const s=this.createSVGElement("circle",{cx:t.x,cy:t.y,r:this.dotRadius,fill:this.color});this.svg.appendChild(s)})}renderBar(t,s){const e=this.data.map(t=>"object"==typeof t?t.value:t),i=this.calculatePoints(e,t,s),h=this.getActualWidth(),a=this.getActualHeight(),r=(h-2*this.padding-this.barGap*(e.length-1))/e.length;i.forEach((t,s)=>{const e=a-2*this.padding-t.y+this.padding,i=t.x-r/2,h=t.y,o=this.createSVGElement("rect",{x:i,y:h,width:r,height:e,fill:this.color,rx:1,"data-bar-index":s,class:"mini-chart-bar"});this.svg.appendChild(o)})}calculatePoints(t,s,e){const i=e-s,h=this.getActualWidth(),a=this.getActualHeight(),r=(h-2*this.padding)/(t.length-1||1),o=(a-2*this.padding)/i;return t.map((t,e)=>({x:this.padding+e*r,y:a-this.padding-(t-s)*o}))}createLinePath(t){if(0===t.length)return"";let s=`M ${t[0].x},${t[0].y}`;for(let e=1;e<t.length;e++)s+=` L ${t[e].x},${t[e].y}`;return s}createSmoothPath(t){if(t.length<2)return this.createLinePath(t);let s=`M ${t[0].x},${t[0].y}`;for(let e=0;e<t.length-1;e++){const i=t[e],h=t[e+1];s+=` C ${i.x+(h.x-i.x)*this.smoothing},${i.y} ${h.x-(h.x-i.x)*this.smoothing},${h.y} ${h.x},${h.y}`}return s}createAreaPath(t){if(0===t.length)return"";const s=this.smoothing>0?this.createSmoothPath(t):this.createLinePath(t),e=t[t.length-1],i=t[0],h=this.getActualHeight();return`${s} L ${e.x},${h-this.padding} L ${i.x},${h-this.padding} Z`}createSVGElement(t,s={}){const e=document.createElementNS("http://www.w3.org/2000/svg",t);return Object.entries(s).forEach(([t,s])=>{e.setAttribute(t,s)}),e}applyAnimation(){this.svg.querySelectorAll("path").forEach(t=>{const s=t.getTotalLength();t.style.strokeDasharray=s,t.style.strokeDashoffset=s,t.style.animation=`mini-chart-draw ${this.animationDuration}ms ease-out forwards`}),this.svg.querySelectorAll("rect").forEach((t,s)=>{t.style.transformOrigin="bottom",t.style.animation=`mini-chart-bar-grow ${this.animationDuration}ms ease-out ${20*s}ms forwards`,t.style.transform="scaleY(0)"})}setupTooltip(){if(!this.svg||!this.tooltip)return;const t=this.data.map(t=>"object"==typeof t?t.value:t),s=this.calculatePoints(t,...Object.values(this.calculateBounds())),e=this.getActualWidth(),i=this.getActualHeight(),h=e/t.length;s.forEach((t,s)=>{const e=this.createSVGElement("rect",{x:s*h,y:0,width:h,height:i,fill:"transparent",style:"cursor: pointer;"});e.addEventListener("mouseenter",t=>{this.showTooltipAtIndex(s,t)}),e.addEventListener("mousemove",t=>{this.updateTooltipPosition(t)}),e.addEventListener("mouseleave",()=>{this.hideTooltip()}),this.svg.appendChild(e)})}showTooltipAtIndex(t,s){if(!this.tooltip)return;this.hoveredIndex=t;const e="object"==typeof this.data[t]?this.data[t].value:this.data[t],i="object"==typeof this.data[t]?this.data[t].label:null;let h=e;this.tooltipFormatter?"function"==typeof this.tooltipFormatter&&(h=this.tooltipFormatter(e,t)):h="number"==typeof e?e.toLocaleString():e;let a=`<strong>${h}</strong>`;if(i&&(a=`${i}<br>${a}`),this.tooltip.innerHTML=a,this.tooltip.style.display="block",this.updateTooltipPosition(s),"bar"===this.chartType&&this.highlightBar(t),this.crosshair&&this.showCrosshair){const s=this.getActualWidth()/this.data.length,e=t*s+s/2;this.crosshair.setAttribute("x1",e),this.crosshair.setAttribute("x2",e),this.crosshair.style.display="block"}}updateTooltipPosition(t){if(!this.tooltip||"none"===this.tooltip.style.display)return;const s=this.svg.getBoundingClientRect(),e=t.clientX-s.left,i=t.clientY-s.top;this.tooltip.style.left=`${e}px`,this.tooltip.style.top=i-10+"px",this.tooltip.style.transform="translate(-50%, -100%)"}hideTooltip(){this.tooltip&&(this.tooltip.style.display="none",this.hoveredIndex=-1),"bar"===this.chartType&&this.unhighlightBars(),this.crosshair&&(this.crosshair.style.display="none")}highlightBar(t){if(!this.svg)return;this.unhighlightBars();const s=this.svg.querySelector(`rect.mini-chart-bar[data-bar-index="${t}"]`);s&&(s.style.opacity="0.7")}unhighlightBars(){this.svg&&this.svg.querySelectorAll("rect.mini-chart-bar").forEach(t=>{t.style.opacity="1"})}setData(t){this.data=t,this.svg&&this.renderChart()}setColor(t){this.color=t,this.svg&&this.renderChart()}setType(t){["line","bar"].includes(t)&&(this.chartType=t,this.svg&&this.renderChart())}resize(t,s){this.width=t,this.height=s,this.updateDimensions(),this.svg&&this.renderChart()}async onBeforeDestroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),await super.onBeforeDestroy()}}exports.BaseChart=t.BaseChart,exports.MetricsChart=t.MetricsChart,exports.PieChart=t.PieChart,exports.SeriesChart=t.SeriesChart,exports.BUILD_TIME=s.BUILD_TIME,exports.VERSION=s.VERSION,exports.VERSION_INFO=s.VERSION_INFO,exports.VERSION_MAJOR=s.VERSION_MAJOR,exports.VERSION_MINOR=s.VERSION_MINOR,exports.VERSION_REVISION=s.VERSION_REVISION,exports.WebApp=s.WebApp,exports.MetricsMiniChart=class extends MiniChart{constructor(t={}){super(t),this.endpoint=t.endpoint||"/api/metrics/fetch",this.account=t.account||"global",this.granularity=t.granularity||"hours",this.slugs=t.slugs||null,this.category=t.category||null,this.dateStart=t.dateStart||null,this.dateEnd=t.dateEnd||null,this.defaultDateRange=t.defaultDateRange||"24h",this.isLoading=!1,this.lastFetch=null,this.refreshInterval=t.refreshInterval,this.dateStart&&this.dateEnd||this.setQuickRange(this.defaultDateRange),this.slugs&&!Array.isArray(this.slugs)&&(this.slugs=[this.slugs])}async onAfterRender(){await super.onAfterRender(),!this.endpoint||this.data&&0!==this.data.length||await this.fetchData(),this.refreshInterval&&this.endpoint&&this.startAutoRefresh()}buildApiParams(){const t={granularity:this.granularity,account:this.account,with_labels:!0};return this.slugs&&this.slugs.length>0&&this.slugs.forEach(s=>{t["slugs[]"]||(t["slugs[]"]=[]),t["slugs[]"].push(s)}),this.category&&(t.category=this.category),this.dateStart&&(t.dr_start=Math.floor(this.dateStart.getTime()/1e3)),this.dateEnd&&(t.dr_end=Math.floor(this.dateEnd.getTime()/1e3)),t._=Date.now(),t}async fetchData(){if(this.endpoint){this.isLoading=!0;try{const t=this.getApp()?.rest;if(!t)throw new Error("No REST client available");const s=this.buildApiParams(),e=await t.GET(this.endpoint,s);if(!e.success)throw new Error(e.message||"Network error");if(!e.data?.status)throw new Error(e.data?.error||"Server error");const i=e.data.data;this.processMetricsData(i),this.lastFetch=/* @__PURE__ */new Date,await this.render(),this.emit("metrics:loaded",{chart:this,data:i,params:s})}catch(t){console.error("Failed to fetch metrics:",t),this.emit("metrics:error",{chart:this,error:t})}finally{this.isLoading=!1}}}processMetricsData(t){const{data:s,labels:e}=t;if(!s)return;const i=Object.keys(s);if(0===i.length)return;const h=s[i[0]].map(t=>null==t||""===t?0:"number"==typeof t?t:parseFloat(t)||0);this.setData(h)}setQuickRange(t){const s=/* @__PURE__ */new Date;let e;switch(t){case"1h":e=new Date(s.getTime()-36e5);break;case"24h":default:e=new Date(s.getTime()-864e5);break;case"7d":e=new Date(s.getTime()-6048e5);break;case"30d":e=new Date(s.getTime()-2592e6)}this.dateStart=e,this.dateEnd=s}startAutoRefresh(){this.refreshTimer&&clearInterval(this.refreshTimer),this.refreshTimer=setInterval(()=>{this.fetchData()},this.refreshInterval)}stopAutoRefresh(){this.refreshTimer&&(clearInterval(this.refreshTimer),this.refreshTimer=null)}setGranularity(t){return this.granularity=t,this.fetchData()}setDateRange(t,s){return this.dateStart=new Date(t),this.dateEnd=new Date(s),this.fetchData()}setMetrics(t){return this.slugs=Array.isArray(t)?t:[t],this.fetchData()}refresh(){return this.fetchData()}async onBeforeDestroy(){this.stopAutoRefresh(),await super.onBeforeDestroy()}},exports.MiniChart=MiniChart;
|
|
2
2
|
//# sourceMappingURL=charts.cjs.js.map
|
package/dist/charts.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"charts.cjs.js","sources":["../src/extensions/charts/MiniChart.js","../src/extensions/charts/MetricsMiniChart.js"],"sourcesContent":["/**\n * MiniChart - Lightweight sparkline chart component\n * Renders simple line or bar charts with minimal configuration\n * Uses SVG for crisp rendering at any size\n */\n\nimport View from '@core/View.js';\n\nexport default class MiniChart extends View {\n constructor(options = {}) {\n super({\n className: 'mini-chart',\n ...options\n });\n\n // Chart type: 'line' or 'bar'\n this.chartType = options.chartType || 'line';\n \n // Data\n this.data = options.data || [];\n \n // Dimensions\n this.width = options.width || '100%'; // Support both number and '100%'\n this.height = options.height || 30;\n this.maintainAspectRatio = options.maintainAspectRatio || false;\n \n // Styling\n this.color = options.color || 'rgba(54, 162, 235, 1)'; // Primary blue\n this.fillColor = options.fillColor || 'rgba(54, 162, 235, 0.1)'; // Light fill\n this.strokeWidth = options.strokeWidth || 2;\n this.barGap = options.barGap || 2;\n \n // Fill area under line\n this.fill = options.fill !== false; // Default true\n \n // Curve smoothing (0 = straight lines, 1 = very smooth)\n this.smoothing = options.smoothing || 0.3;\n \n // Padding\n this.padding = options.padding || 2;\n \n // Min/Max values (auto-calculated if not provided)\n this.minValue = options.minValue;\n this.maxValue = options.maxValue;\n \n // Show dots on line chart\n this.showDots = options.showDots || false;\n this.dotRadius = options.dotRadius || 2;\n \n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 300;\n \n // Tooltip\n this.showTooltip = options.showTooltip !== false;\n this.tooltipFormatter = options.tooltipFormatter || null;\n \n // Crosshair\n this.showCrosshair = options.showCrosshair !== false;\n this.crosshairColor = options.crosshairColor || 'rgba(0, 0, 0, 0.2)';\n this.crosshairWidth = options.crosshairWidth || 1;\n \n // Tooltip state\n this.tooltip = null;\n this.crosshair = null;\n this.hoveredIndex = -1;\n }\n\n getTemplate() {\n const widthStyle = typeof this.width === 'number' ? `${this.width}px` : this.width;\n const heightStyle = typeof this.height === 'number' ? `${this.height}px` : this.height;\n const preserveAspectRatio = this.maintainAspectRatio ? 'xMidYMid meet' : 'none';\n \n return `\n <div class=\"mini-chart-wrapper\" style=\"position: relative; display: block; width: ${widthStyle}; height: ${heightStyle};\">\n <svg \n class=\"mini-chart-svg\" \n width=\"100%\" \n height=\"100%\"\n viewBox=\"0 0 100 ${this.height}\"\n preserveAspectRatio=\"${preserveAspectRatio}\"\n style=\"display: block;\">\n </svg>\n ${this.showTooltip ? '<div class=\"mini-chart-tooltip\" style=\"display: none;\"></div>' : ''}\n </div>\n `;\n }\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.mini-chart-svg');\n this.tooltip = this.element.querySelector('.mini-chart-tooltip');\n \n // Get actual rendered dimensions\n this.updateDimensions();\n \n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n \n // Setup hover interactions if tooltip enabled\n if (this.showTooltip && this.svg) {\n this.setupTooltip();\n }\n \n // Setup resize observer for responsive behavior\n this.setupResizeObserver();\n }\n\n updateDimensions() {\n if (!this.svg) return;\n \n const rect = this.svg.getBoundingClientRect();\n this.actualWidth = rect.width || 100;\n this.actualHeight = rect.height || this.height;\n \n // Update viewBox to match aspect ratio\n this.svg.setAttribute('viewBox', `0 0 ${this.actualWidth} ${this.actualHeight}`);\n }\n\n setupResizeObserver() {\n if (typeof ResizeObserver === 'undefined') return;\n \n this.resizeObserver = new ResizeObserver(() => {\n this.updateDimensions();\n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n });\n \n if (this.svg) {\n this.resizeObserver.observe(this.svg);\n }\n }\n\n renderChart() {\n if (!this.svg || !this.data || this.data.length === 0) return;\n\n // Clear previous content\n this.svg.innerHTML = '';\n\n // Calculate bounds\n const { min, max } = this.calculateBounds();\n \n if (this.chartType === 'line') {\n this.renderLine(min, max);\n } else if (this.chartType === 'bar') {\n this.renderBar(min, max);\n }\n\n // Add crosshair line (initially hidden)\n if (this.showCrosshair) {\n const height = this.getActualHeight();\n this.crosshair = this.createSVGElement('line', {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: height,\n stroke: this.crosshairColor,\n 'stroke-width': this.crosshairWidth,\n 'stroke-dasharray': '3,3',\n style: 'display: none; pointer-events: none;'\n });\n this.svg.appendChild(this.crosshair);\n }\n\n // Setup tooltip hit areas after rendering chart\n if (this.showTooltip && this.tooltip) {\n this.setupTooltip();\n }\n\n // Apply animation if enabled\n if (this.animate) {\n this.applyAnimation();\n }\n }\n\n calculateBounds() {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n \n let min = this.minValue !== undefined ? this.minValue : Math.min(...values);\n let max = this.maxValue !== undefined ? this.maxValue : Math.max(...values);\n \n // Add padding to range\n const range = max - min;\n if (range === 0) {\n min = min - 1;\n max = max + 1;\n }\n \n return { min, max };\n }\n\n getActualWidth() {\n return this.actualWidth || this.width || 100;\n }\n\n getActualHeight() {\n return this.actualHeight || this.height || 30;\n }\n\n renderLine(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n \n // Create filled area under line\n if (this.fill) {\n const areaPath = this.createAreaPath(points);\n const area = this.createSVGElement('path', {\n d: areaPath,\n fill: this.fillColor,\n stroke: 'none'\n });\n this.svg.appendChild(area);\n }\n \n // Create line path\n const linePath = this.smoothing > 0 \n ? this.createSmoothPath(points) \n : this.createLinePath(points);\n \n const line = this.createSVGElement('path', {\n d: linePath,\n fill: 'none',\n stroke: this.color,\n 'stroke-width': this.strokeWidth,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round'\n });\n this.svg.appendChild(line);\n \n // Add dots if enabled\n if (this.showDots) {\n points.forEach(point => {\n const dot = this.createSVGElement('circle', {\n cx: point.x,\n cy: point.y,\n r: this.dotRadius,\n fill: this.color\n });\n this.svg.appendChild(dot);\n });\n }\n }\n\n renderBar(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n \n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = (width - this.padding * 2 - (this.barGap * (values.length - 1))) / values.length;\n \n points.forEach((point, index) => {\n const barHeight = height - this.padding * 2 - point.y + this.padding;\n const x = point.x - barWidth / 2;\n const y = point.y;\n \n const bar = this.createSVGElement('rect', {\n x: x,\n y: y,\n width: barWidth,\n height: barHeight,\n fill: this.color,\n rx: 1, // Slight rounding\n 'data-bar-index': index,\n class: 'mini-chart-bar'\n });\n this.svg.appendChild(bar);\n });\n }\n\n calculatePoints(values, min, max) {\n const range = max - min;\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const xStep = (width - this.padding * 2) / (values.length - 1 || 1);\n const yScale = (height - this.padding * 2) / range;\n \n return values.map((value, index) => ({\n x: this.padding + (index * xStep),\n y: height - this.padding - ((value - min) * yScale)\n }));\n }\n\n createLinePath(points) {\n if (points.length === 0) return '';\n \n let path = `M ${points[0].x},${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n path += ` L ${points[i].x},${points[i].y}`;\n }\n return path;\n }\n\n createSmoothPath(points) {\n if (points.length < 2) return this.createLinePath(points);\n \n let path = `M ${points[0].x},${points[0].y}`;\n \n for (let i = 0; i < points.length - 1; i++) {\n const current = points[i];\n const next = points[i + 1];\n \n // Calculate control points for cubic bezier curve\n const cp1x = current.x + (next.x - current.x) * this.smoothing;\n const cp1y = current.y;\n const cp2x = next.x - (next.x - current.x) * this.smoothing;\n const cp2y = next.y;\n \n path += ` C ${cp1x},${cp1y} ${cp2x},${cp2y} ${next.x},${next.y}`;\n }\n \n return path;\n }\n\n createAreaPath(points) {\n if (points.length === 0) return '';\n \n const linePath = this.smoothing > 0 \n ? this.createSmoothPath(points) \n : this.createLinePath(points);\n \n // Close the path along the bottom\n const lastPoint = points[points.length - 1];\n const firstPoint = points[0];\n const height = this.getActualHeight();\n \n return `${linePath} L ${lastPoint.x},${height - this.padding} L ${firstPoint.x},${height - this.padding} Z`;\n }\n\n createSVGElement(tag, attributes = {}) {\n const element = document.createElementNS('http://www.w3.org/2000/svg', tag);\n Object.entries(attributes).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n return element;\n }\n\n applyAnimation() {\n const paths = this.svg.querySelectorAll('path');\n paths.forEach(path => {\n const length = path.getTotalLength();\n path.style.strokeDasharray = length;\n path.style.strokeDashoffset = length;\n path.style.animation = `mini-chart-draw ${this.animationDuration}ms ease-out forwards`;\n });\n \n const bars = this.svg.querySelectorAll('rect');\n bars.forEach((bar, index) => {\n bar.style.transformOrigin = 'bottom';\n bar.style.animation = `mini-chart-bar-grow ${this.animationDuration}ms ease-out ${index * 20}ms forwards`;\n bar.style.transform = 'scaleY(0)';\n });\n }\n\n setupTooltip() {\n if (!this.svg || !this.tooltip) return;\n \n // Create invisible overlay rects for hover detection\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, ...Object.values(this.calculateBounds()));\n \n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = width / values.length;\n \n points.forEach((point, index) => {\n const hitArea = this.createSVGElement('rect', {\n x: index * barWidth,\n y: 0,\n width: barWidth,\n height: height,\n fill: 'transparent',\n style: 'cursor: pointer;'\n });\n \n hitArea.addEventListener('mouseenter', (e) => {\n this.showTooltipAtIndex(index, e);\n });\n \n hitArea.addEventListener('mousemove', (e) => {\n this.updateTooltipPosition(e);\n });\n \n hitArea.addEventListener('mouseleave', () => {\n this.hideTooltip();\n });\n \n this.svg.appendChild(hitArea);\n });\n }\n\n showTooltipAtIndex(index, event) {\n if (!this.tooltip) return;\n \n this.hoveredIndex = index;\n const value = typeof this.data[index] === 'object' ? this.data[index].value : this.data[index];\n const label = typeof this.data[index] === 'object' ? this.data[index].label : null;\n \n // Format the value\n let displayValue = value;\n if (this.tooltipFormatter) {\n if (typeof this.tooltipFormatter === 'function') {\n displayValue = this.tooltipFormatter(value, index);\n }\n } else {\n displayValue = typeof value === 'number' ? value.toLocaleString() : value;\n }\n \n // Build tooltip content\n let content = `<strong>${displayValue}</strong>`;\n if (label) {\n content = `${label}<br>${content}`;\n }\n \n this.tooltip.innerHTML = content;\n this.tooltip.style.display = 'block';\n this.updateTooltipPosition(event);\n \n // Highlight bar if in bar chart mode\n if (this.chartType === 'bar') {\n this.highlightBar(index);\n }\n \n // Show crosshair at the hovered position\n if (this.crosshair && this.showCrosshair) {\n const width = this.getActualWidth();\n const barWidth = width / this.data.length;\n const x = (index * barWidth) + (barWidth / 2);\n this.crosshair.setAttribute('x1', x);\n this.crosshair.setAttribute('x2', x);\n this.crosshair.style.display = 'block';\n }\n }\n\n updateTooltipPosition(event) {\n if (!this.tooltip || this.tooltip.style.display === 'none') return;\n \n const rect = this.svg.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n \n // Position tooltip above cursor\n this.tooltip.style.left = `${x}px`;\n this.tooltip.style.top = `${y - 10}px`;\n this.tooltip.style.transform = 'translate(-50%, -100%)';\n }\n\n hideTooltip() {\n if (this.tooltip) {\n this.tooltip.style.display = 'none';\n this.hoveredIndex = -1;\n }\n \n // Remove bar highlight\n if (this.chartType === 'bar') {\n this.unhighlightBars();\n }\n \n // Hide crosshair\n if (this.crosshair) {\n this.crosshair.style.display = 'none';\n }\n }\n\n highlightBar(index) {\n if (!this.svg) return;\n \n // Remove previous highlights\n this.unhighlightBars();\n \n // Highlight the hovered bar\n const bar = this.svg.querySelector(`rect.mini-chart-bar[data-bar-index=\"${index}\"]`);\n if (bar) {\n bar.style.opacity = '0.7';\n }\n }\n\n unhighlightBars() {\n if (!this.svg) return;\n \n const bars = this.svg.querySelectorAll('rect.mini-chart-bar');\n bars.forEach(bar => {\n bar.style.opacity = '1';\n });\n }\n\n // Public API\n setData(data) {\n this.data = data;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setColor(color) {\n this.color = color;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setType(type) {\n if (['line', 'bar'].includes(type)) {\n this.chartType = type;\n if (this.svg) {\n this.renderChart();\n }\n }\n }\n\n resize(width, height) {\n this.width = width;\n this.height = height;\n this.updateDimensions();\n if (this.svg) {\n this.renderChart();\n }\n }\n\n async onBeforeDestroy() {\n // Clean up resize observer\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n await super.onBeforeDestroy();\n }\n}\n","/**\n * MetricsMiniChart - MiniChart with API integration\n * Extends MiniChart to add /api/metrics/fetch support (same API as MetricsChart)\n */\n\nimport MiniChart from './MiniChart.js';\n\nexport default class MetricsMiniChart extends MiniChart {\n constructor(options = {}) {\n super(options);\n \n // API configuration (matching MetricsChart)\n this.endpoint = options.endpoint || '/api/metrics/fetch';\n this.account = options.account || 'global';\n this.granularity = options.granularity || 'hours';\n this.slugs = options.slugs || null; // Single slug or array of slugs\n this.category = options.category || null;\n this.dateStart = options.dateStart || null;\n this.dateEnd = options.dateEnd || null;\n this.defaultDateRange = options.defaultDateRange || '24h';\n \n // State\n this.isLoading = false;\n this.lastFetch = null;\n this.refreshInterval = options.refreshInterval;\n \n // Initialize date range if missing\n if (!this.dateStart || !this.dateEnd) {\n this.setQuickRange(this.defaultDateRange);\n }\n \n // Normalize slugs to array\n if (this.slugs && !Array.isArray(this.slugs)) {\n this.slugs = [this.slugs];\n }\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n \n // Fetch initial data if endpoint provided and no data\n if (this.endpoint && (!this.data || this.data.length === 0)) {\n await this.fetchData();\n }\n \n // Setup auto-refresh if configured\n if (this.refreshInterval && this.endpoint) {\n this.startAutoRefresh();\n }\n }\n\n buildApiParams() {\n const params = {\n granularity: this.granularity,\n account: this.account,\n with_labels: true\n };\n\n // Add slugs\n if (this.slugs && this.slugs.length > 0) {\n this.slugs.forEach(slug => {\n if (!params['slugs[]']) params['slugs[]'] = [];\n params['slugs[]'].push(slug);\n });\n }\n\n if (this.category) {\n params.category = this.category;\n }\n\n // Date range\n if (this.dateStart) {\n params.dr_start = Math.floor(this.dateStart.getTime() / 1000);\n }\n if (this.dateEnd) {\n params.dr_end = Math.floor(this.dateEnd.getTime() / 1000);\n }\n\n // Cache buster\n params._ = Date.now();\n\n return params;\n }\n\n async fetchData() {\n if (!this.endpoint) return;\n \n this.isLoading = true;\n \n try {\n const rest = this.getApp()?.rest;\n if (!rest) {\n throw new Error('No REST client available');\n }\n \n const params = this.buildApiParams();\n const response = await rest.GET(this.endpoint, params);\n \n // Handle Rest standardized response\n if (!response.success) {\n throw new Error(response.message || 'Network error');\n }\n if (!response.data?.status) {\n throw new Error(response.data?.error || 'Server error');\n }\n \n const metricsData = response.data.data;\n this.processMetricsData(metricsData);\n this.lastFetch = new Date();\n \n // Re-render to show updated values\n await this.render();\n \n this.emit('metrics:loaded', { chart: this, data: metricsData, params });\n \n } catch (error) {\n console.error('Failed to fetch metrics:', error);\n this.emit('metrics:error', { chart: this, error });\n } finally {\n this.isLoading = false;\n }\n }\n\n processMetricsData(metricsData) {\n // Expecting: { labels: [...], data: { metric_slug: [values...] } }\n const { data: metrics, labels } = metricsData;\n \n if (!metrics) return;\n \n // Get the first (or only) metric's data\n const metricKeys = Object.keys(metrics);\n if (metricKeys.length === 0) return;\n \n const metricSlug = metricKeys[0];\n const values = metrics[metricSlug];\n \n // Sanitize values\n const sanitizedValues = values.map(val => {\n if (val === null || val === undefined || val === '') return 0;\n return typeof val === 'number' ? val : (parseFloat(val) || 0);\n });\n \n // Update chart data\n this.setData(sanitizedValues);\n }\n\n setQuickRange(range) {\n const now = new Date();\n let startDate;\n\n switch (range) {\n case '1h':\n startDate = new Date(now.getTime() - (60 * 60 * 1000));\n break;\n case '24h':\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n break;\n case '7d':\n startDate = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));\n break;\n case '30d':\n startDate = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));\n break;\n default:\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n }\n\n this.dateStart = startDate;\n this.dateEnd = now;\n }\n\n startAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n }\n \n this.refreshTimer = setInterval(() => {\n this.fetchData();\n }, this.refreshInterval);\n }\n\n stopAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n // Public API\n setGranularity(granularity) {\n this.granularity = granularity;\n return this.fetchData();\n }\n\n setDateRange(startDate, endDate) {\n this.dateStart = new Date(startDate);\n this.dateEnd = new Date(endDate);\n return this.fetchData();\n }\n\n setMetrics(slugs) {\n this.slugs = Array.isArray(slugs) ? slugs : [slugs];\n return this.fetchData();\n }\n\n refresh() {\n return this.fetchData();\n }\n\n async onBeforeDestroy() {\n this.stopAutoRefresh();\n await super.onBeforeDestroy();\n }\n}\n"],"names":["MiniChart","View","constructor","options","super","className","this","chartType","data","width","height","maintainAspectRatio","color","fillColor","strokeWidth","barGap","fill","smoothing","padding","minValue","maxValue","showDots","dotRadius","animate","animationDuration","showTooltip","tooltipFormatter","showCrosshair","crosshairColor","crosshairWidth","tooltip","crosshair","hoveredIndex","getTemplate","widthStyle","heightStyle","preserveAspectRatio","onAfterRender","svg","element","querySelector","updateDimensions","length","renderChart","setupTooltip","setupResizeObserver","rect","getBoundingClientRect","actualWidth","actualHeight","setAttribute","ResizeObserver","resizeObserver","observe","innerHTML","min","max","calculateBounds","renderLine","renderBar","getActualHeight","createSVGElement","x1","y1","x2","y2","stroke","style","appendChild","applyAnimation","values","map","d","value","Math","getActualWidth","points","calculatePoints","areaPath","createAreaPath","area","linePath","createSmoothPath","createLinePath","line","forEach","point","dot","cx","x","cy","y","r","barWidth","index","barHeight","bar","rx","class","range","xStep","yScale","path","i","current","next","lastPoint","firstPoint","tag","attributes","document","createElementNS","Object","entries","key","querySelectorAll","getTotalLength","strokeDasharray","strokeDashoffset","animation","transformOrigin","transform","hitArea","addEventListener","e","showTooltipAtIndex","updateTooltipPosition","hideTooltip","event","label","displayValue","toLocaleString","content","display","highlightBar","clientX","left","clientY","top","unhighlightBars","opacity","setData","setColor","setType","type","includes","resize","onBeforeDestroy","disconnect","endpoint","account","granularity","slugs","category","dateStart","dateEnd","defaultDateRange","isLoading","lastFetch","refreshInterval","setQuickRange","Array","isArray","fetchData","startAutoRefresh","buildApiParams","params","with_labels","slug","push","dr_start","floor","getTime","dr_end","_","Date","now","rest","getApp","Error","response","GET","success","message","status","error","metricsData","processMetricsData","render","emit","chart","console","metrics","labels","metricKeys","keys","sanitizedValues","val","parseFloat","startDate","refreshTimer","clearInterval","setInterval","stopAutoRefresh","setGranularity","setDateRange","endDate","setMetrics","refresh"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"charts.cjs.js","sources":["../src/extensions/charts/MiniChart.js","../src/extensions/charts/MetricsMiniChart.js"],"sourcesContent":["/**\n * MiniChart - Lightweight sparkline chart component\n * Renders simple line or bar charts with minimal configuration\n * Uses SVG for crisp rendering at any size\n */\n\nimport View from '@core/View.js';\n\nexport default class MiniChart extends View {\n constructor(options = {}) {\n super({\n className: 'mini-chart',\n ...options\n });\n\n // Chart type: 'line' or 'bar'\n this.chartType = options.chartType || 'line';\n \n // Data\n this.data = options.data || [];\n \n // Dimensions\n this.width = options.width || '100%'; // Support both number and '100%'\n this.height = options.height || 30;\n this.maintainAspectRatio = options.maintainAspectRatio || false;\n \n // Styling\n this.color = options.color || 'rgba(54, 162, 235, 1)'; // Primary blue\n this.fillColor = options.fillColor || 'rgba(54, 162, 235, 0.1)'; // Light fill\n this.strokeWidth = options.strokeWidth || 2;\n this.barGap = options.barGap || 2;\n \n // Fill area under line\n this.fill = options.fill !== false; // Default true\n \n // Curve smoothing (0 = straight lines, 1 = very smooth)\n this.smoothing = options.smoothing || 0.3;\n \n // Padding\n this.padding = options.padding || 2;\n \n // Min/Max values (auto-calculated if not provided)\n this.minValue = options.minValue;\n this.maxValue = options.maxValue;\n \n // Show dots on line chart\n this.showDots = options.showDots || false;\n this.dotRadius = options.dotRadius || 2;\n \n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 300;\n \n // Tooltip\n this.showTooltip = options.showTooltip !== false;\n this.tooltipFormatter = options.tooltipFormatter || null;\n \n // Crosshair\n this.showCrosshair = options.showCrosshair !== false;\n this.crosshairColor = options.crosshairColor || 'rgba(0, 0, 0, 0.2)';\n this.crosshairWidth = options.crosshairWidth || 1;\n \n // X-axis\n this.showXAxis = options.showXAxis || false;\n this.xAxisColor = options.xAxisColor || this.color;\n this.xAxisWidth = options.xAxisWidth || 1;\n this.xAxisDashed = options.xAxisDashed !== false;\n \n // Tooltip state\n this.tooltip = null;\n this.crosshair = null;\n this.hoveredIndex = -1;\n }\n\n getTemplate() {\n const widthStyle = typeof this.width === 'number' ? `${this.width}px` : this.width;\n const heightStyle = typeof this.height === 'number' ? `${this.height}px` : this.height;\n const preserveAspectRatio = this.maintainAspectRatio ? 'xMidYMid meet' : 'none';\n \n return `\n <div class=\"mini-chart-wrapper\" style=\"position: relative; display: block; width: ${widthStyle}; height: ${heightStyle};\">\n <svg \n class=\"mini-chart-svg\" \n width=\"100%\" \n height=\"100%\"\n viewBox=\"0 0 100 ${this.height}\"\n preserveAspectRatio=\"${preserveAspectRatio}\"\n style=\"display: block;\">\n </svg>\n ${this.showTooltip ? '<div class=\"mini-chart-tooltip\" style=\"display: none;\"></div>' : ''}\n </div>\n `;\n }\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.mini-chart-svg');\n this.tooltip = this.element.querySelector('.mini-chart-tooltip');\n \n // Get actual rendered dimensions\n this.updateDimensions();\n \n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n \n // Setup hover interactions if tooltip enabled\n if (this.showTooltip && this.svg) {\n this.setupTooltip();\n }\n \n // Setup resize observer for responsive behavior\n this.setupResizeObserver();\n }\n\n updateDimensions() {\n if (!this.svg) return;\n \n const rect = this.svg.getBoundingClientRect();\n this.actualWidth = rect.width || 100;\n this.actualHeight = rect.height || this.height;\n \n // Update viewBox to match aspect ratio\n this.svg.setAttribute('viewBox', `0 0 ${this.actualWidth} ${this.actualHeight}`);\n }\n\n setupResizeObserver() {\n if (typeof ResizeObserver === 'undefined') return;\n \n this.resizeObserver = new ResizeObserver(() => {\n this.updateDimensions();\n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n });\n \n if (this.svg) {\n this.resizeObserver.observe(this.svg);\n }\n }\n\n renderChart() {\n if (!this.svg || !this.data || this.data.length === 0) return;\n\n // Clear previous content\n this.svg.innerHTML = '';\n\n // Calculate bounds\n const { min, max } = this.calculateBounds();\n \n // Add x-axis line if enabled (render first so it's behind chart)\n if (this.showXAxis) {\n this.renderXAxis(min, max);\n }\n \n if (this.chartType === 'line') {\n this.renderLine(min, max);\n } else if (this.chartType === 'bar') {\n this.renderBar(min, max);\n }\n\n // Add crosshair line (initially hidden)\n if (this.showCrosshair) {\n const height = this.getActualHeight();\n this.crosshair = this.createSVGElement('line', {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: height,\n stroke: this.crosshairColor,\n 'stroke-width': this.crosshairWidth,\n 'stroke-dasharray': '3,3',\n style: 'display: none; pointer-events: none;'\n });\n this.svg.appendChild(this.crosshair);\n }\n\n // Setup tooltip hit areas after rendering chart\n if (this.showTooltip && this.tooltip) {\n this.setupTooltip();\n }\n\n // Apply animation if enabled\n if (this.animate) {\n this.applyAnimation();\n }\n }\n\n renderXAxis(min, max) {\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n \n // Calculate y position for x-axis (at zero if data crosses zero, otherwise at bottom)\n let yPos;\n if (min <= 0 && max >= 0) {\n // Data crosses zero, place axis at zero\n const range = max - min;\n const yScale = (height - this.padding * 2) / range;\n yPos = height - this.padding - ((0 - min) * yScale);\n } else {\n // Place at bottom\n yPos = height - this.padding;\n }\n \n const xAxis = this.createSVGElement('line', {\n x1: this.padding,\n y1: yPos,\n x2: width - this.padding,\n y2: yPos,\n stroke: this.xAxisColor,\n 'stroke-width': this.xAxisWidth,\n 'stroke-dasharray': this.xAxisDashed ? '2,2' : 'none',\n 'stroke-opacity': '0.5'\n });\n \n this.svg.appendChild(xAxis);\n }\n\n calculateBounds() {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n \n let min = this.minValue !== undefined ? this.minValue : Math.min(...values);\n let max = this.maxValue !== undefined ? this.maxValue : Math.max(...values);\n \n // Add padding to range\n const range = max - min;\n if (range === 0) {\n min = min - 1;\n max = max + 1;\n }\n \n return { min, max };\n }\n\n getActualWidth() {\n return this.actualWidth || this.width || 100;\n }\n\n getActualHeight() {\n return this.actualHeight || this.height || 30;\n }\n\n renderLine(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n \n // Create filled area under line\n if (this.fill) {\n const areaPath = this.createAreaPath(points);\n const area = this.createSVGElement('path', {\n d: areaPath,\n fill: this.fillColor,\n stroke: 'none'\n });\n this.svg.appendChild(area);\n }\n \n // Create line path\n const linePath = this.smoothing > 0 \n ? this.createSmoothPath(points) \n : this.createLinePath(points);\n \n const line = this.createSVGElement('path', {\n d: linePath,\n fill: 'none',\n stroke: this.color,\n 'stroke-width': this.strokeWidth,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round'\n });\n this.svg.appendChild(line);\n \n // Add dots if enabled\n if (this.showDots) {\n points.forEach(point => {\n const dot = this.createSVGElement('circle', {\n cx: point.x,\n cy: point.y,\n r: this.dotRadius,\n fill: this.color\n });\n this.svg.appendChild(dot);\n });\n }\n }\n\n renderBar(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n \n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = (width - this.padding * 2 - (this.barGap * (values.length - 1))) / values.length;\n \n points.forEach((point, index) => {\n const barHeight = height - this.padding * 2 - point.y + this.padding;\n const x = point.x - barWidth / 2;\n const y = point.y;\n \n const bar = this.createSVGElement('rect', {\n x: x,\n y: y,\n width: barWidth,\n height: barHeight,\n fill: this.color,\n rx: 1, // Slight rounding\n 'data-bar-index': index,\n class: 'mini-chart-bar'\n });\n this.svg.appendChild(bar);\n });\n }\n\n calculatePoints(values, min, max) {\n const range = max - min;\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const xStep = (width - this.padding * 2) / (values.length - 1 || 1);\n const yScale = (height - this.padding * 2) / range;\n \n return values.map((value, index) => ({\n x: this.padding + (index * xStep),\n y: height - this.padding - ((value - min) * yScale)\n }));\n }\n\n createLinePath(points) {\n if (points.length === 0) return '';\n \n let path = `M ${points[0].x},${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n path += ` L ${points[i].x},${points[i].y}`;\n }\n return path;\n }\n\n createSmoothPath(points) {\n if (points.length < 2) return this.createLinePath(points);\n \n let path = `M ${points[0].x},${points[0].y}`;\n \n for (let i = 0; i < points.length - 1; i++) {\n const current = points[i];\n const next = points[i + 1];\n \n // Calculate control points for cubic bezier curve\n const cp1x = current.x + (next.x - current.x) * this.smoothing;\n const cp1y = current.y;\n const cp2x = next.x - (next.x - current.x) * this.smoothing;\n const cp2y = next.y;\n \n path += ` C ${cp1x},${cp1y} ${cp2x},${cp2y} ${next.x},${next.y}`;\n }\n \n return path;\n }\n\n createAreaPath(points) {\n if (points.length === 0) return '';\n \n const linePath = this.smoothing > 0 \n ? this.createSmoothPath(points) \n : this.createLinePath(points);\n \n // Close the path along the bottom\n const lastPoint = points[points.length - 1];\n const firstPoint = points[0];\n const height = this.getActualHeight();\n \n return `${linePath} L ${lastPoint.x},${height - this.padding} L ${firstPoint.x},${height - this.padding} Z`;\n }\n\n createSVGElement(tag, attributes = {}) {\n const element = document.createElementNS('http://www.w3.org/2000/svg', tag);\n Object.entries(attributes).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n return element;\n }\n\n applyAnimation() {\n const paths = this.svg.querySelectorAll('path');\n paths.forEach(path => {\n const length = path.getTotalLength();\n path.style.strokeDasharray = length;\n path.style.strokeDashoffset = length;\n path.style.animation = `mini-chart-draw ${this.animationDuration}ms ease-out forwards`;\n });\n \n const bars = this.svg.querySelectorAll('rect');\n bars.forEach((bar, index) => {\n bar.style.transformOrigin = 'bottom';\n bar.style.animation = `mini-chart-bar-grow ${this.animationDuration}ms ease-out ${index * 20}ms forwards`;\n bar.style.transform = 'scaleY(0)';\n });\n }\n\n setupTooltip() {\n if (!this.svg || !this.tooltip) return;\n \n // Create invisible overlay rects for hover detection\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, ...Object.values(this.calculateBounds()));\n \n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = width / values.length;\n \n points.forEach((point, index) => {\n const hitArea = this.createSVGElement('rect', {\n x: index * barWidth,\n y: 0,\n width: barWidth,\n height: height,\n fill: 'transparent',\n style: 'cursor: pointer;'\n });\n \n hitArea.addEventListener('mouseenter', (e) => {\n this.showTooltipAtIndex(index, e);\n });\n \n hitArea.addEventListener('mousemove', (e) => {\n this.updateTooltipPosition(e);\n });\n \n hitArea.addEventListener('mouseleave', () => {\n this.hideTooltip();\n });\n \n this.svg.appendChild(hitArea);\n });\n }\n\n showTooltipAtIndex(index, event) {\n if (!this.tooltip) return;\n \n this.hoveredIndex = index;\n const value = typeof this.data[index] === 'object' ? this.data[index].value : this.data[index];\n const label = typeof this.data[index] === 'object' ? this.data[index].label : null;\n \n // Format the value\n let displayValue = value;\n if (this.tooltipFormatter) {\n if (typeof this.tooltipFormatter === 'function') {\n displayValue = this.tooltipFormatter(value, index);\n }\n } else {\n displayValue = typeof value === 'number' ? value.toLocaleString() : value;\n }\n \n // Build tooltip content\n let content = `<strong>${displayValue}</strong>`;\n if (label) {\n content = `${label}<br>${content}`;\n }\n \n this.tooltip.innerHTML = content;\n this.tooltip.style.display = 'block';\n this.updateTooltipPosition(event);\n \n // Highlight bar if in bar chart mode\n if (this.chartType === 'bar') {\n this.highlightBar(index);\n }\n \n // Show crosshair at the hovered position\n if (this.crosshair && this.showCrosshair) {\n const width = this.getActualWidth();\n const barWidth = width / this.data.length;\n const x = (index * barWidth) + (barWidth / 2);\n this.crosshair.setAttribute('x1', x);\n this.crosshair.setAttribute('x2', x);\n this.crosshair.style.display = 'block';\n }\n }\n\n updateTooltipPosition(event) {\n if (!this.tooltip || this.tooltip.style.display === 'none') return;\n \n const rect = this.svg.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n \n // Position tooltip above cursor\n this.tooltip.style.left = `${x}px`;\n this.tooltip.style.top = `${y - 10}px`;\n this.tooltip.style.transform = 'translate(-50%, -100%)';\n }\n\n hideTooltip() {\n if (this.tooltip) {\n this.tooltip.style.display = 'none';\n this.hoveredIndex = -1;\n }\n \n // Remove bar highlight\n if (this.chartType === 'bar') {\n this.unhighlightBars();\n }\n \n // Hide crosshair\n if (this.crosshair) {\n this.crosshair.style.display = 'none';\n }\n }\n\n highlightBar(index) {\n if (!this.svg) return;\n \n // Remove previous highlights\n this.unhighlightBars();\n \n // Highlight the hovered bar\n const bar = this.svg.querySelector(`rect.mini-chart-bar[data-bar-index=\"${index}\"]`);\n if (bar) {\n bar.style.opacity = '0.7';\n }\n }\n\n unhighlightBars() {\n if (!this.svg) return;\n \n const bars = this.svg.querySelectorAll('rect.mini-chart-bar');\n bars.forEach(bar => {\n bar.style.opacity = '1';\n });\n }\n\n // Public API\n setData(data) {\n this.data = data;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setColor(color) {\n this.color = color;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setType(type) {\n if (['line', 'bar'].includes(type)) {\n this.chartType = type;\n if (this.svg) {\n this.renderChart();\n }\n }\n }\n\n resize(width, height) {\n this.width = width;\n this.height = height;\n this.updateDimensions();\n if (this.svg) {\n this.renderChart();\n }\n }\n\n async onBeforeDestroy() {\n // Clean up resize observer\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n await super.onBeforeDestroy();\n }\n}\n","/**\n * MetricsMiniChart - MiniChart with API integration\n * Extends MiniChart to add /api/metrics/fetch support (same API as MetricsChart)\n */\n\nimport MiniChart from './MiniChart.js';\n\nexport default class MetricsMiniChart extends MiniChart {\n constructor(options = {}) {\n super(options);\n \n // API configuration (matching MetricsChart)\n this.endpoint = options.endpoint || '/api/metrics/fetch';\n this.account = options.account || 'global';\n this.granularity = options.granularity || 'hours';\n this.slugs = options.slugs || null; // Single slug or array of slugs\n this.category = options.category || null;\n this.dateStart = options.dateStart || null;\n this.dateEnd = options.dateEnd || null;\n this.defaultDateRange = options.defaultDateRange || '24h';\n \n // State\n this.isLoading = false;\n this.lastFetch = null;\n this.refreshInterval = options.refreshInterval;\n \n // Initialize date range if missing\n if (!this.dateStart || !this.dateEnd) {\n this.setQuickRange(this.defaultDateRange);\n }\n \n // Normalize slugs to array\n if (this.slugs && !Array.isArray(this.slugs)) {\n this.slugs = [this.slugs];\n }\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n \n // Fetch initial data if endpoint provided and no data\n if (this.endpoint && (!this.data || this.data.length === 0)) {\n await this.fetchData();\n }\n \n // Setup auto-refresh if configured\n if (this.refreshInterval && this.endpoint) {\n this.startAutoRefresh();\n }\n }\n\n buildApiParams() {\n const params = {\n granularity: this.granularity,\n account: this.account,\n with_labels: true\n };\n\n // Add slugs\n if (this.slugs && this.slugs.length > 0) {\n this.slugs.forEach(slug => {\n if (!params['slugs[]']) params['slugs[]'] = [];\n params['slugs[]'].push(slug);\n });\n }\n\n if (this.category) {\n params.category = this.category;\n }\n\n // Date range\n if (this.dateStart) {\n params.dr_start = Math.floor(this.dateStart.getTime() / 1000);\n }\n if (this.dateEnd) {\n params.dr_end = Math.floor(this.dateEnd.getTime() / 1000);\n }\n\n // Cache buster\n params._ = Date.now();\n\n return params;\n }\n\n async fetchData() {\n if (!this.endpoint) return;\n \n this.isLoading = true;\n \n try {\n const rest = this.getApp()?.rest;\n if (!rest) {\n throw new Error('No REST client available');\n }\n \n const params = this.buildApiParams();\n const response = await rest.GET(this.endpoint, params);\n \n // Handle Rest standardized response\n if (!response.success) {\n throw new Error(response.message || 'Network error');\n }\n if (!response.data?.status) {\n throw new Error(response.data?.error || 'Server error');\n }\n \n const metricsData = response.data.data;\n this.processMetricsData(metricsData);\n this.lastFetch = new Date();\n \n // Re-render to show updated values\n await this.render();\n \n this.emit('metrics:loaded', { chart: this, data: metricsData, params });\n \n } catch (error) {\n console.error('Failed to fetch metrics:', error);\n this.emit('metrics:error', { chart: this, error });\n } finally {\n this.isLoading = false;\n }\n }\n\n processMetricsData(metricsData) {\n // Expecting: { labels: [...], data: { metric_slug: [values...] } }\n const { data: metrics, labels } = metricsData;\n \n if (!metrics) return;\n \n // Get the first (or only) metric's data\n const metricKeys = Object.keys(metrics);\n if (metricKeys.length === 0) return;\n \n const metricSlug = metricKeys[0];\n const values = metrics[metricSlug];\n \n // Sanitize values\n const sanitizedValues = values.map(val => {\n if (val === null || val === undefined || val === '') return 0;\n return typeof val === 'number' ? val : (parseFloat(val) || 0);\n });\n \n // Update chart data\n this.setData(sanitizedValues);\n }\n\n setQuickRange(range) {\n const now = new Date();\n let startDate;\n\n switch (range) {\n case '1h':\n startDate = new Date(now.getTime() - (60 * 60 * 1000));\n break;\n case '24h':\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n break;\n case '7d':\n startDate = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));\n break;\n case '30d':\n startDate = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));\n break;\n default:\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n }\n\n this.dateStart = startDate;\n this.dateEnd = now;\n }\n\n startAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n }\n \n this.refreshTimer = setInterval(() => {\n this.fetchData();\n }, this.refreshInterval);\n }\n\n stopAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n // Public API\n setGranularity(granularity) {\n this.granularity = granularity;\n return this.fetchData();\n }\n\n setDateRange(startDate, endDate) {\n this.dateStart = new Date(startDate);\n this.dateEnd = new Date(endDate);\n return this.fetchData();\n }\n\n setMetrics(slugs) {\n this.slugs = Array.isArray(slugs) ? slugs : [slugs];\n return this.fetchData();\n }\n\n refresh() {\n return this.fetchData();\n }\n\n async onBeforeDestroy() {\n this.stopAutoRefresh();\n await super.onBeforeDestroy();\n }\n}\n"],"names":["MiniChart","View","constructor","options","super","className","this","chartType","data","width","height","maintainAspectRatio","color","fillColor","strokeWidth","barGap","fill","smoothing","padding","minValue","maxValue","showDots","dotRadius","animate","animationDuration","showTooltip","tooltipFormatter","showCrosshair","crosshairColor","crosshairWidth","showXAxis","xAxisColor","xAxisWidth","xAxisDashed","tooltip","crosshair","hoveredIndex","getTemplate","widthStyle","heightStyle","preserveAspectRatio","onAfterRender","svg","element","querySelector","updateDimensions","length","renderChart","setupTooltip","setupResizeObserver","rect","getBoundingClientRect","actualWidth","actualHeight","setAttribute","ResizeObserver","resizeObserver","observe","innerHTML","min","max","calculateBounds","renderXAxis","renderLine","renderBar","getActualHeight","createSVGElement","x1","y1","x2","y2","stroke","style","appendChild","applyAnimation","getActualWidth","yPos","range","yScale","xAxis","values","map","d","value","Math","points","calculatePoints","areaPath","createAreaPath","area","linePath","createSmoothPath","createLinePath","line","forEach","point","dot","cx","x","cy","y","r","barWidth","index","barHeight","bar","rx","class","xStep","path","i","current","next","lastPoint","firstPoint","tag","attributes","document","createElementNS","Object","entries","key","querySelectorAll","getTotalLength","strokeDasharray","strokeDashoffset","animation","transformOrigin","transform","hitArea","addEventListener","e","showTooltipAtIndex","updateTooltipPosition","hideTooltip","event","label","displayValue","toLocaleString","content","display","highlightBar","clientX","left","clientY","top","unhighlightBars","opacity","setData","setColor","setType","type","includes","resize","onBeforeDestroy","disconnect","endpoint","account","granularity","slugs","category","dateStart","dateEnd","defaultDateRange","isLoading","lastFetch","refreshInterval","setQuickRange","Array","isArray","fetchData","startAutoRefresh","buildApiParams","params","with_labels","slug","push","dr_start","floor","getTime","dr_end","_","Date","now","rest","getApp","Error","response","GET","success","message","status","error","metricsData","processMetricsData","render","emit","chart","console","metrics","labels","metricKeys","keys","sanitizedValues","val","parseFloat","startDate","refreshTimer","clearInterval","setInterval","stopAutoRefresh","setGranularity","setDateRange","endDate","setMetrics","refresh"],"mappings":"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"}
|
package/dist/charts.es.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { B, M, P, S } from "./chunks/MetricsChart-
|
|
2
|
-
import { V as View } from "./chunks/WebApp-
|
|
3
|
-
import { B as B2, b, a, c, e, f, W } from "./chunks/WebApp-
|
|
1
|
+
import { B, M, P, S } from "./chunks/MetricsChart-Bbn-L_9C.js";
|
|
2
|
+
import { V as View } from "./chunks/WebApp-zyQ4x8MK.js";
|
|
3
|
+
import { B as B2, b, a, c, e, f, W } from "./chunks/WebApp-zyQ4x8MK.js";
|
|
4
4
|
class MiniChart extends View {
|
|
5
5
|
constructor(options = {}) {
|
|
6
6
|
super({
|
|
@@ -30,6 +30,10 @@ class MiniChart extends View {
|
|
|
30
30
|
this.showCrosshair = options.showCrosshair !== false;
|
|
31
31
|
this.crosshairColor = options.crosshairColor || "rgba(0, 0, 0, 0.2)";
|
|
32
32
|
this.crosshairWidth = options.crosshairWidth || 1;
|
|
33
|
+
this.showXAxis = options.showXAxis || false;
|
|
34
|
+
this.xAxisColor = options.xAxisColor || this.color;
|
|
35
|
+
this.xAxisWidth = options.xAxisWidth || 1;
|
|
36
|
+
this.xAxisDashed = options.xAxisDashed !== false;
|
|
33
37
|
this.tooltip = null;
|
|
34
38
|
this.crosshair = null;
|
|
35
39
|
this.hoveredIndex = -1;
|
|
@@ -87,6 +91,9 @@ class MiniChart extends View {
|
|
|
87
91
|
if (!this.svg || !this.data || this.data.length === 0) return;
|
|
88
92
|
this.svg.innerHTML = "";
|
|
89
93
|
const { min, max } = this.calculateBounds();
|
|
94
|
+
if (this.showXAxis) {
|
|
95
|
+
this.renderXAxis(min, max);
|
|
96
|
+
}
|
|
90
97
|
if (this.chartType === "line") {
|
|
91
98
|
this.renderLine(min, max);
|
|
92
99
|
} else if (this.chartType === "bar") {
|
|
@@ -113,6 +120,29 @@ class MiniChart extends View {
|
|
|
113
120
|
this.applyAnimation();
|
|
114
121
|
}
|
|
115
122
|
}
|
|
123
|
+
renderXAxis(min, max) {
|
|
124
|
+
const width = this.getActualWidth();
|
|
125
|
+
const height = this.getActualHeight();
|
|
126
|
+
let yPos;
|
|
127
|
+
if (min <= 0 && max >= 0) {
|
|
128
|
+
const range = max - min;
|
|
129
|
+
const yScale = (height - this.padding * 2) / range;
|
|
130
|
+
yPos = height - this.padding - (0 - min) * yScale;
|
|
131
|
+
} else {
|
|
132
|
+
yPos = height - this.padding;
|
|
133
|
+
}
|
|
134
|
+
const xAxis = this.createSVGElement("line", {
|
|
135
|
+
x1: this.padding,
|
|
136
|
+
y1: yPos,
|
|
137
|
+
x2: width - this.padding,
|
|
138
|
+
y2: yPos,
|
|
139
|
+
stroke: this.xAxisColor,
|
|
140
|
+
"stroke-width": this.xAxisWidth,
|
|
141
|
+
"stroke-dasharray": this.xAxisDashed ? "2,2" : "none",
|
|
142
|
+
"stroke-opacity": "0.5"
|
|
143
|
+
});
|
|
144
|
+
this.svg.appendChild(xAxis);
|
|
145
|
+
}
|
|
116
146
|
calculateBounds() {
|
|
117
147
|
const values = this.data.map((d) => typeof d === "object" ? d.value : d);
|
|
118
148
|
let min = this.minValue !== void 0 ? this.minValue : Math.min(...values);
|
package/dist/charts.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"charts.es.js","sources":["../src/extensions/charts/MiniChart.js","../src/extensions/charts/MetricsMiniChart.js"],"sourcesContent":["/**\n * MiniChart - Lightweight sparkline chart component\n * Renders simple line or bar charts with minimal configuration\n * Uses SVG for crisp rendering at any size\n */\n\nimport View from '@core/View.js';\n\nexport default class MiniChart extends View {\n constructor(options = {}) {\n super({\n className: 'mini-chart',\n ...options\n });\n\n // Chart type: 'line' or 'bar'\n this.chartType = options.chartType || 'line';\n \n // Data\n this.data = options.data || [];\n \n // Dimensions\n this.width = options.width || '100%'; // Support both number and '100%'\n this.height = options.height || 30;\n this.maintainAspectRatio = options.maintainAspectRatio || false;\n \n // Styling\n this.color = options.color || 'rgba(54, 162, 235, 1)'; // Primary blue\n this.fillColor = options.fillColor || 'rgba(54, 162, 235, 0.1)'; // Light fill\n this.strokeWidth = options.strokeWidth || 2;\n this.barGap = options.barGap || 2;\n \n // Fill area under line\n this.fill = options.fill !== false; // Default true\n \n // Curve smoothing (0 = straight lines, 1 = very smooth)\n this.smoothing = options.smoothing || 0.3;\n \n // Padding\n this.padding = options.padding || 2;\n \n // Min/Max values (auto-calculated if not provided)\n this.minValue = options.minValue;\n this.maxValue = options.maxValue;\n \n // Show dots on line chart\n this.showDots = options.showDots || false;\n this.dotRadius = options.dotRadius || 2;\n \n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 300;\n \n // Tooltip\n this.showTooltip = options.showTooltip !== false;\n this.tooltipFormatter = options.tooltipFormatter || null;\n \n // Crosshair\n this.showCrosshair = options.showCrosshair !== false;\n this.crosshairColor = options.crosshairColor || 'rgba(0, 0, 0, 0.2)';\n this.crosshairWidth = options.crosshairWidth || 1;\n \n // Tooltip state\n this.tooltip = null;\n this.crosshair = null;\n this.hoveredIndex = -1;\n }\n\n getTemplate() {\n const widthStyle = typeof this.width === 'number' ? `${this.width}px` : this.width;\n const heightStyle = typeof this.height === 'number' ? `${this.height}px` : this.height;\n const preserveAspectRatio = this.maintainAspectRatio ? 'xMidYMid meet' : 'none';\n \n return `\n <div class=\"mini-chart-wrapper\" style=\"position: relative; display: block; width: ${widthStyle}; height: ${heightStyle};\">\n <svg \n class=\"mini-chart-svg\" \n width=\"100%\" \n height=\"100%\"\n viewBox=\"0 0 100 ${this.height}\"\n preserveAspectRatio=\"${preserveAspectRatio}\"\n style=\"display: block;\">\n </svg>\n ${this.showTooltip ? '<div class=\"mini-chart-tooltip\" style=\"display: none;\"></div>' : ''}\n </div>\n `;\n }\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.mini-chart-svg');\n this.tooltip = this.element.querySelector('.mini-chart-tooltip');\n \n // Get actual rendered dimensions\n this.updateDimensions();\n \n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n \n // Setup hover interactions if tooltip enabled\n if (this.showTooltip && this.svg) {\n this.setupTooltip();\n }\n \n // Setup resize observer for responsive behavior\n this.setupResizeObserver();\n }\n\n updateDimensions() {\n if (!this.svg) return;\n \n const rect = this.svg.getBoundingClientRect();\n this.actualWidth = rect.width || 100;\n this.actualHeight = rect.height || this.height;\n \n // Update viewBox to match aspect ratio\n this.svg.setAttribute('viewBox', `0 0 ${this.actualWidth} ${this.actualHeight}`);\n }\n\n setupResizeObserver() {\n if (typeof ResizeObserver === 'undefined') return;\n \n this.resizeObserver = new ResizeObserver(() => {\n this.updateDimensions();\n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n });\n \n if (this.svg) {\n this.resizeObserver.observe(this.svg);\n }\n }\n\n renderChart() {\n if (!this.svg || !this.data || this.data.length === 0) return;\n\n // Clear previous content\n this.svg.innerHTML = '';\n\n // Calculate bounds\n const { min, max } = this.calculateBounds();\n \n if (this.chartType === 'line') {\n this.renderLine(min, max);\n } else if (this.chartType === 'bar') {\n this.renderBar(min, max);\n }\n\n // Add crosshair line (initially hidden)\n if (this.showCrosshair) {\n const height = this.getActualHeight();\n this.crosshair = this.createSVGElement('line', {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: height,\n stroke: this.crosshairColor,\n 'stroke-width': this.crosshairWidth,\n 'stroke-dasharray': '3,3',\n style: 'display: none; pointer-events: none;'\n });\n this.svg.appendChild(this.crosshair);\n }\n\n // Setup tooltip hit areas after rendering chart\n if (this.showTooltip && this.tooltip) {\n this.setupTooltip();\n }\n\n // Apply animation if enabled\n if (this.animate) {\n this.applyAnimation();\n }\n }\n\n calculateBounds() {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n \n let min = this.minValue !== undefined ? this.minValue : Math.min(...values);\n let max = this.maxValue !== undefined ? this.maxValue : Math.max(...values);\n \n // Add padding to range\n const range = max - min;\n if (range === 0) {\n min = min - 1;\n max = max + 1;\n }\n \n return { min, max };\n }\n\n getActualWidth() {\n return this.actualWidth || this.width || 100;\n }\n\n getActualHeight() {\n return this.actualHeight || this.height || 30;\n }\n\n renderLine(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n \n // Create filled area under line\n if (this.fill) {\n const areaPath = this.createAreaPath(points);\n const area = this.createSVGElement('path', {\n d: areaPath,\n fill: this.fillColor,\n stroke: 'none'\n });\n this.svg.appendChild(area);\n }\n \n // Create line path\n const linePath = this.smoothing > 0 \n ? this.createSmoothPath(points) \n : this.createLinePath(points);\n \n const line = this.createSVGElement('path', {\n d: linePath,\n fill: 'none',\n stroke: this.color,\n 'stroke-width': this.strokeWidth,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round'\n });\n this.svg.appendChild(line);\n \n // Add dots if enabled\n if (this.showDots) {\n points.forEach(point => {\n const dot = this.createSVGElement('circle', {\n cx: point.x,\n cy: point.y,\n r: this.dotRadius,\n fill: this.color\n });\n this.svg.appendChild(dot);\n });\n }\n }\n\n renderBar(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n \n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = (width - this.padding * 2 - (this.barGap * (values.length - 1))) / values.length;\n \n points.forEach((point, index) => {\n const barHeight = height - this.padding * 2 - point.y + this.padding;\n const x = point.x - barWidth / 2;\n const y = point.y;\n \n const bar = this.createSVGElement('rect', {\n x: x,\n y: y,\n width: barWidth,\n height: barHeight,\n fill: this.color,\n rx: 1, // Slight rounding\n 'data-bar-index': index,\n class: 'mini-chart-bar'\n });\n this.svg.appendChild(bar);\n });\n }\n\n calculatePoints(values, min, max) {\n const range = max - min;\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const xStep = (width - this.padding * 2) / (values.length - 1 || 1);\n const yScale = (height - this.padding * 2) / range;\n \n return values.map((value, index) => ({\n x: this.padding + (index * xStep),\n y: height - this.padding - ((value - min) * yScale)\n }));\n }\n\n createLinePath(points) {\n if (points.length === 0) return '';\n \n let path = `M ${points[0].x},${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n path += ` L ${points[i].x},${points[i].y}`;\n }\n return path;\n }\n\n createSmoothPath(points) {\n if (points.length < 2) return this.createLinePath(points);\n \n let path = `M ${points[0].x},${points[0].y}`;\n \n for (let i = 0; i < points.length - 1; i++) {\n const current = points[i];\n const next = points[i + 1];\n \n // Calculate control points for cubic bezier curve\n const cp1x = current.x + (next.x - current.x) * this.smoothing;\n const cp1y = current.y;\n const cp2x = next.x - (next.x - current.x) * this.smoothing;\n const cp2y = next.y;\n \n path += ` C ${cp1x},${cp1y} ${cp2x},${cp2y} ${next.x},${next.y}`;\n }\n \n return path;\n }\n\n createAreaPath(points) {\n if (points.length === 0) return '';\n \n const linePath = this.smoothing > 0 \n ? this.createSmoothPath(points) \n : this.createLinePath(points);\n \n // Close the path along the bottom\n const lastPoint = points[points.length - 1];\n const firstPoint = points[0];\n const height = this.getActualHeight();\n \n return `${linePath} L ${lastPoint.x},${height - this.padding} L ${firstPoint.x},${height - this.padding} Z`;\n }\n\n createSVGElement(tag, attributes = {}) {\n const element = document.createElementNS('http://www.w3.org/2000/svg', tag);\n Object.entries(attributes).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n return element;\n }\n\n applyAnimation() {\n const paths = this.svg.querySelectorAll('path');\n paths.forEach(path => {\n const length = path.getTotalLength();\n path.style.strokeDasharray = length;\n path.style.strokeDashoffset = length;\n path.style.animation = `mini-chart-draw ${this.animationDuration}ms ease-out forwards`;\n });\n \n const bars = this.svg.querySelectorAll('rect');\n bars.forEach((bar, index) => {\n bar.style.transformOrigin = 'bottom';\n bar.style.animation = `mini-chart-bar-grow ${this.animationDuration}ms ease-out ${index * 20}ms forwards`;\n bar.style.transform = 'scaleY(0)';\n });\n }\n\n setupTooltip() {\n if (!this.svg || !this.tooltip) return;\n \n // Create invisible overlay rects for hover detection\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, ...Object.values(this.calculateBounds()));\n \n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = width / values.length;\n \n points.forEach((point, index) => {\n const hitArea = this.createSVGElement('rect', {\n x: index * barWidth,\n y: 0,\n width: barWidth,\n height: height,\n fill: 'transparent',\n style: 'cursor: pointer;'\n });\n \n hitArea.addEventListener('mouseenter', (e) => {\n this.showTooltipAtIndex(index, e);\n });\n \n hitArea.addEventListener('mousemove', (e) => {\n this.updateTooltipPosition(e);\n });\n \n hitArea.addEventListener('mouseleave', () => {\n this.hideTooltip();\n });\n \n this.svg.appendChild(hitArea);\n });\n }\n\n showTooltipAtIndex(index, event) {\n if (!this.tooltip) return;\n \n this.hoveredIndex = index;\n const value = typeof this.data[index] === 'object' ? this.data[index].value : this.data[index];\n const label = typeof this.data[index] === 'object' ? this.data[index].label : null;\n \n // Format the value\n let displayValue = value;\n if (this.tooltipFormatter) {\n if (typeof this.tooltipFormatter === 'function') {\n displayValue = this.tooltipFormatter(value, index);\n }\n } else {\n displayValue = typeof value === 'number' ? value.toLocaleString() : value;\n }\n \n // Build tooltip content\n let content = `<strong>${displayValue}</strong>`;\n if (label) {\n content = `${label}<br>${content}`;\n }\n \n this.tooltip.innerHTML = content;\n this.tooltip.style.display = 'block';\n this.updateTooltipPosition(event);\n \n // Highlight bar if in bar chart mode\n if (this.chartType === 'bar') {\n this.highlightBar(index);\n }\n \n // Show crosshair at the hovered position\n if (this.crosshair && this.showCrosshair) {\n const width = this.getActualWidth();\n const barWidth = width / this.data.length;\n const x = (index * barWidth) + (barWidth / 2);\n this.crosshair.setAttribute('x1', x);\n this.crosshair.setAttribute('x2', x);\n this.crosshair.style.display = 'block';\n }\n }\n\n updateTooltipPosition(event) {\n if (!this.tooltip || this.tooltip.style.display === 'none') return;\n \n const rect = this.svg.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n \n // Position tooltip above cursor\n this.tooltip.style.left = `${x}px`;\n this.tooltip.style.top = `${y - 10}px`;\n this.tooltip.style.transform = 'translate(-50%, -100%)';\n }\n\n hideTooltip() {\n if (this.tooltip) {\n this.tooltip.style.display = 'none';\n this.hoveredIndex = -1;\n }\n \n // Remove bar highlight\n if (this.chartType === 'bar') {\n this.unhighlightBars();\n }\n \n // Hide crosshair\n if (this.crosshair) {\n this.crosshair.style.display = 'none';\n }\n }\n\n highlightBar(index) {\n if (!this.svg) return;\n \n // Remove previous highlights\n this.unhighlightBars();\n \n // Highlight the hovered bar\n const bar = this.svg.querySelector(`rect.mini-chart-bar[data-bar-index=\"${index}\"]`);\n if (bar) {\n bar.style.opacity = '0.7';\n }\n }\n\n unhighlightBars() {\n if (!this.svg) return;\n \n const bars = this.svg.querySelectorAll('rect.mini-chart-bar');\n bars.forEach(bar => {\n bar.style.opacity = '1';\n });\n }\n\n // Public API\n setData(data) {\n this.data = data;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setColor(color) {\n this.color = color;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setType(type) {\n if (['line', 'bar'].includes(type)) {\n this.chartType = type;\n if (this.svg) {\n this.renderChart();\n }\n }\n }\n\n resize(width, height) {\n this.width = width;\n this.height = height;\n this.updateDimensions();\n if (this.svg) {\n this.renderChart();\n }\n }\n\n async onBeforeDestroy() {\n // Clean up resize observer\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n await super.onBeforeDestroy();\n }\n}\n","/**\n * MetricsMiniChart - MiniChart with API integration\n * Extends MiniChart to add /api/metrics/fetch support (same API as MetricsChart)\n */\n\nimport MiniChart from './MiniChart.js';\n\nexport default class MetricsMiniChart extends MiniChart {\n constructor(options = {}) {\n super(options);\n \n // API configuration (matching MetricsChart)\n this.endpoint = options.endpoint || '/api/metrics/fetch';\n this.account = options.account || 'global';\n this.granularity = options.granularity || 'hours';\n this.slugs = options.slugs || null; // Single slug or array of slugs\n this.category = options.category || null;\n this.dateStart = options.dateStart || null;\n this.dateEnd = options.dateEnd || null;\n this.defaultDateRange = options.defaultDateRange || '24h';\n \n // State\n this.isLoading = false;\n this.lastFetch = null;\n this.refreshInterval = options.refreshInterval;\n \n // Initialize date range if missing\n if (!this.dateStart || !this.dateEnd) {\n this.setQuickRange(this.defaultDateRange);\n }\n \n // Normalize slugs to array\n if (this.slugs && !Array.isArray(this.slugs)) {\n this.slugs = [this.slugs];\n }\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n \n // Fetch initial data if endpoint provided and no data\n if (this.endpoint && (!this.data || this.data.length === 0)) {\n await this.fetchData();\n }\n \n // Setup auto-refresh if configured\n if (this.refreshInterval && this.endpoint) {\n this.startAutoRefresh();\n }\n }\n\n buildApiParams() {\n const params = {\n granularity: this.granularity,\n account: this.account,\n with_labels: true\n };\n\n // Add slugs\n if (this.slugs && this.slugs.length > 0) {\n this.slugs.forEach(slug => {\n if (!params['slugs[]']) params['slugs[]'] = [];\n params['slugs[]'].push(slug);\n });\n }\n\n if (this.category) {\n params.category = this.category;\n }\n\n // Date range\n if (this.dateStart) {\n params.dr_start = Math.floor(this.dateStart.getTime() / 1000);\n }\n if (this.dateEnd) {\n params.dr_end = Math.floor(this.dateEnd.getTime() / 1000);\n }\n\n // Cache buster\n params._ = Date.now();\n\n return params;\n }\n\n async fetchData() {\n if (!this.endpoint) return;\n \n this.isLoading = true;\n \n try {\n const rest = this.getApp()?.rest;\n if (!rest) {\n throw new Error('No REST client available');\n }\n \n const params = this.buildApiParams();\n const response = await rest.GET(this.endpoint, params);\n \n // Handle Rest standardized response\n if (!response.success) {\n throw new Error(response.message || 'Network error');\n }\n if (!response.data?.status) {\n throw new Error(response.data?.error || 'Server error');\n }\n \n const metricsData = response.data.data;\n this.processMetricsData(metricsData);\n this.lastFetch = new Date();\n \n // Re-render to show updated values\n await this.render();\n \n this.emit('metrics:loaded', { chart: this, data: metricsData, params });\n \n } catch (error) {\n console.error('Failed to fetch metrics:', error);\n this.emit('metrics:error', { chart: this, error });\n } finally {\n this.isLoading = false;\n }\n }\n\n processMetricsData(metricsData) {\n // Expecting: { labels: [...], data: { metric_slug: [values...] } }\n const { data: metrics, labels } = metricsData;\n \n if (!metrics) return;\n \n // Get the first (or only) metric's data\n const metricKeys = Object.keys(metrics);\n if (metricKeys.length === 0) return;\n \n const metricSlug = metricKeys[0];\n const values = metrics[metricSlug];\n \n // Sanitize values\n const sanitizedValues = values.map(val => {\n if (val === null || val === undefined || val === '') return 0;\n return typeof val === 'number' ? val : (parseFloat(val) || 0);\n });\n \n // Update chart data\n this.setData(sanitizedValues);\n }\n\n setQuickRange(range) {\n const now = new Date();\n let startDate;\n\n switch (range) {\n case '1h':\n startDate = new Date(now.getTime() - (60 * 60 * 1000));\n break;\n case '24h':\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n break;\n case '7d':\n startDate = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));\n break;\n case '30d':\n startDate = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));\n break;\n default:\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n }\n\n this.dateStart = startDate;\n this.dateEnd = now;\n }\n\n startAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n }\n \n this.refreshTimer = setInterval(() => {\n this.fetchData();\n }, this.refreshInterval);\n }\n\n stopAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n // Public API\n setGranularity(granularity) {\n this.granularity = granularity;\n return this.fetchData();\n }\n\n setDateRange(startDate, endDate) {\n this.dateStart = new Date(startDate);\n this.dateEnd = new Date(endDate);\n return this.fetchData();\n }\n\n setMetrics(slugs) {\n this.slugs = Array.isArray(slugs) ? slugs : [slugs];\n return this.fetchData();\n }\n\n refresh() {\n return this.fetchData();\n }\n\n async onBeforeDestroy() {\n this.stopAutoRefresh();\n await super.onBeforeDestroy();\n }\n}\n"],"names":["e"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"charts.es.js","sources":["../src/extensions/charts/MiniChart.js","../src/extensions/charts/MetricsMiniChart.js"],"sourcesContent":["/**\n * MiniChart - Lightweight sparkline chart component\n * Renders simple line or bar charts with minimal configuration\n * Uses SVG for crisp rendering at any size\n */\n\nimport View from '@core/View.js';\n\nexport default class MiniChart extends View {\n constructor(options = {}) {\n super({\n className: 'mini-chart',\n ...options\n });\n\n // Chart type: 'line' or 'bar'\n this.chartType = options.chartType || 'line';\n \n // Data\n this.data = options.data || [];\n \n // Dimensions\n this.width = options.width || '100%'; // Support both number and '100%'\n this.height = options.height || 30;\n this.maintainAspectRatio = options.maintainAspectRatio || false;\n \n // Styling\n this.color = options.color || 'rgba(54, 162, 235, 1)'; // Primary blue\n this.fillColor = options.fillColor || 'rgba(54, 162, 235, 0.1)'; // Light fill\n this.strokeWidth = options.strokeWidth || 2;\n this.barGap = options.barGap || 2;\n \n // Fill area under line\n this.fill = options.fill !== false; // Default true\n \n // Curve smoothing (0 = straight lines, 1 = very smooth)\n this.smoothing = options.smoothing || 0.3;\n \n // Padding\n this.padding = options.padding || 2;\n \n // Min/Max values (auto-calculated if not provided)\n this.minValue = options.minValue;\n this.maxValue = options.maxValue;\n \n // Show dots on line chart\n this.showDots = options.showDots || false;\n this.dotRadius = options.dotRadius || 2;\n \n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 300;\n \n // Tooltip\n this.showTooltip = options.showTooltip !== false;\n this.tooltipFormatter = options.tooltipFormatter || null;\n \n // Crosshair\n this.showCrosshair = options.showCrosshair !== false;\n this.crosshairColor = options.crosshairColor || 'rgba(0, 0, 0, 0.2)';\n this.crosshairWidth = options.crosshairWidth || 1;\n \n // X-axis\n this.showXAxis = options.showXAxis || false;\n this.xAxisColor = options.xAxisColor || this.color;\n this.xAxisWidth = options.xAxisWidth || 1;\n this.xAxisDashed = options.xAxisDashed !== false;\n \n // Tooltip state\n this.tooltip = null;\n this.crosshair = null;\n this.hoveredIndex = -1;\n }\n\n getTemplate() {\n const widthStyle = typeof this.width === 'number' ? `${this.width}px` : this.width;\n const heightStyle = typeof this.height === 'number' ? `${this.height}px` : this.height;\n const preserveAspectRatio = this.maintainAspectRatio ? 'xMidYMid meet' : 'none';\n \n return `\n <div class=\"mini-chart-wrapper\" style=\"position: relative; display: block; width: ${widthStyle}; height: ${heightStyle};\">\n <svg \n class=\"mini-chart-svg\" \n width=\"100%\" \n height=\"100%\"\n viewBox=\"0 0 100 ${this.height}\"\n preserveAspectRatio=\"${preserveAspectRatio}\"\n style=\"display: block;\">\n </svg>\n ${this.showTooltip ? '<div class=\"mini-chart-tooltip\" style=\"display: none;\"></div>' : ''}\n </div>\n `;\n }\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.mini-chart-svg');\n this.tooltip = this.element.querySelector('.mini-chart-tooltip');\n \n // Get actual rendered dimensions\n this.updateDimensions();\n \n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n \n // Setup hover interactions if tooltip enabled\n if (this.showTooltip && this.svg) {\n this.setupTooltip();\n }\n \n // Setup resize observer for responsive behavior\n this.setupResizeObserver();\n }\n\n updateDimensions() {\n if (!this.svg) return;\n \n const rect = this.svg.getBoundingClientRect();\n this.actualWidth = rect.width || 100;\n this.actualHeight = rect.height || this.height;\n \n // Update viewBox to match aspect ratio\n this.svg.setAttribute('viewBox', `0 0 ${this.actualWidth} ${this.actualHeight}`);\n }\n\n setupResizeObserver() {\n if (typeof ResizeObserver === 'undefined') return;\n \n this.resizeObserver = new ResizeObserver(() => {\n this.updateDimensions();\n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n });\n \n if (this.svg) {\n this.resizeObserver.observe(this.svg);\n }\n }\n\n renderChart() {\n if (!this.svg || !this.data || this.data.length === 0) return;\n\n // Clear previous content\n this.svg.innerHTML = '';\n\n // Calculate bounds\n const { min, max } = this.calculateBounds();\n \n // Add x-axis line if enabled (render first so it's behind chart)\n if (this.showXAxis) {\n this.renderXAxis(min, max);\n }\n \n if (this.chartType === 'line') {\n this.renderLine(min, max);\n } else if (this.chartType === 'bar') {\n this.renderBar(min, max);\n }\n\n // Add crosshair line (initially hidden)\n if (this.showCrosshair) {\n const height = this.getActualHeight();\n this.crosshair = this.createSVGElement('line', {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: height,\n stroke: this.crosshairColor,\n 'stroke-width': this.crosshairWidth,\n 'stroke-dasharray': '3,3',\n style: 'display: none; pointer-events: none;'\n });\n this.svg.appendChild(this.crosshair);\n }\n\n // Setup tooltip hit areas after rendering chart\n if (this.showTooltip && this.tooltip) {\n this.setupTooltip();\n }\n\n // Apply animation if enabled\n if (this.animate) {\n this.applyAnimation();\n }\n }\n\n renderXAxis(min, max) {\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n \n // Calculate y position for x-axis (at zero if data crosses zero, otherwise at bottom)\n let yPos;\n if (min <= 0 && max >= 0) {\n // Data crosses zero, place axis at zero\n const range = max - min;\n const yScale = (height - this.padding * 2) / range;\n yPos = height - this.padding - ((0 - min) * yScale);\n } else {\n // Place at bottom\n yPos = height - this.padding;\n }\n \n const xAxis = this.createSVGElement('line', {\n x1: this.padding,\n y1: yPos,\n x2: width - this.padding,\n y2: yPos,\n stroke: this.xAxisColor,\n 'stroke-width': this.xAxisWidth,\n 'stroke-dasharray': this.xAxisDashed ? '2,2' : 'none',\n 'stroke-opacity': '0.5'\n });\n \n this.svg.appendChild(xAxis);\n }\n\n calculateBounds() {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n \n let min = this.minValue !== undefined ? this.minValue : Math.min(...values);\n let max = this.maxValue !== undefined ? this.maxValue : Math.max(...values);\n \n // Add padding to range\n const range = max - min;\n if (range === 0) {\n min = min - 1;\n max = max + 1;\n }\n \n return { min, max };\n }\n\n getActualWidth() {\n return this.actualWidth || this.width || 100;\n }\n\n getActualHeight() {\n return this.actualHeight || this.height || 30;\n }\n\n renderLine(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n \n // Create filled area under line\n if (this.fill) {\n const areaPath = this.createAreaPath(points);\n const area = this.createSVGElement('path', {\n d: areaPath,\n fill: this.fillColor,\n stroke: 'none'\n });\n this.svg.appendChild(area);\n }\n \n // Create line path\n const linePath = this.smoothing > 0 \n ? this.createSmoothPath(points) \n : this.createLinePath(points);\n \n const line = this.createSVGElement('path', {\n d: linePath,\n fill: 'none',\n stroke: this.color,\n 'stroke-width': this.strokeWidth,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round'\n });\n this.svg.appendChild(line);\n \n // Add dots if enabled\n if (this.showDots) {\n points.forEach(point => {\n const dot = this.createSVGElement('circle', {\n cx: point.x,\n cy: point.y,\n r: this.dotRadius,\n fill: this.color\n });\n this.svg.appendChild(dot);\n });\n }\n }\n\n renderBar(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n \n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = (width - this.padding * 2 - (this.barGap * (values.length - 1))) / values.length;\n \n points.forEach((point, index) => {\n const barHeight = height - this.padding * 2 - point.y + this.padding;\n const x = point.x - barWidth / 2;\n const y = point.y;\n \n const bar = this.createSVGElement('rect', {\n x: x,\n y: y,\n width: barWidth,\n height: barHeight,\n fill: this.color,\n rx: 1, // Slight rounding\n 'data-bar-index': index,\n class: 'mini-chart-bar'\n });\n this.svg.appendChild(bar);\n });\n }\n\n calculatePoints(values, min, max) {\n const range = max - min;\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const xStep = (width - this.padding * 2) / (values.length - 1 || 1);\n const yScale = (height - this.padding * 2) / range;\n \n return values.map((value, index) => ({\n x: this.padding + (index * xStep),\n y: height - this.padding - ((value - min) * yScale)\n }));\n }\n\n createLinePath(points) {\n if (points.length === 0) return '';\n \n let path = `M ${points[0].x},${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n path += ` L ${points[i].x},${points[i].y}`;\n }\n return path;\n }\n\n createSmoothPath(points) {\n if (points.length < 2) return this.createLinePath(points);\n \n let path = `M ${points[0].x},${points[0].y}`;\n \n for (let i = 0; i < points.length - 1; i++) {\n const current = points[i];\n const next = points[i + 1];\n \n // Calculate control points for cubic bezier curve\n const cp1x = current.x + (next.x - current.x) * this.smoothing;\n const cp1y = current.y;\n const cp2x = next.x - (next.x - current.x) * this.smoothing;\n const cp2y = next.y;\n \n path += ` C ${cp1x},${cp1y} ${cp2x},${cp2y} ${next.x},${next.y}`;\n }\n \n return path;\n }\n\n createAreaPath(points) {\n if (points.length === 0) return '';\n \n const linePath = this.smoothing > 0 \n ? this.createSmoothPath(points) \n : this.createLinePath(points);\n \n // Close the path along the bottom\n const lastPoint = points[points.length - 1];\n const firstPoint = points[0];\n const height = this.getActualHeight();\n \n return `${linePath} L ${lastPoint.x},${height - this.padding} L ${firstPoint.x},${height - this.padding} Z`;\n }\n\n createSVGElement(tag, attributes = {}) {\n const element = document.createElementNS('http://www.w3.org/2000/svg', tag);\n Object.entries(attributes).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n return element;\n }\n\n applyAnimation() {\n const paths = this.svg.querySelectorAll('path');\n paths.forEach(path => {\n const length = path.getTotalLength();\n path.style.strokeDasharray = length;\n path.style.strokeDashoffset = length;\n path.style.animation = `mini-chart-draw ${this.animationDuration}ms ease-out forwards`;\n });\n \n const bars = this.svg.querySelectorAll('rect');\n bars.forEach((bar, index) => {\n bar.style.transformOrigin = 'bottom';\n bar.style.animation = `mini-chart-bar-grow ${this.animationDuration}ms ease-out ${index * 20}ms forwards`;\n bar.style.transform = 'scaleY(0)';\n });\n }\n\n setupTooltip() {\n if (!this.svg || !this.tooltip) return;\n \n // Create invisible overlay rects for hover detection\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, ...Object.values(this.calculateBounds()));\n \n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = width / values.length;\n \n points.forEach((point, index) => {\n const hitArea = this.createSVGElement('rect', {\n x: index * barWidth,\n y: 0,\n width: barWidth,\n height: height,\n fill: 'transparent',\n style: 'cursor: pointer;'\n });\n \n hitArea.addEventListener('mouseenter', (e) => {\n this.showTooltipAtIndex(index, e);\n });\n \n hitArea.addEventListener('mousemove', (e) => {\n this.updateTooltipPosition(e);\n });\n \n hitArea.addEventListener('mouseleave', () => {\n this.hideTooltip();\n });\n \n this.svg.appendChild(hitArea);\n });\n }\n\n showTooltipAtIndex(index, event) {\n if (!this.tooltip) return;\n \n this.hoveredIndex = index;\n const value = typeof this.data[index] === 'object' ? this.data[index].value : this.data[index];\n const label = typeof this.data[index] === 'object' ? this.data[index].label : null;\n \n // Format the value\n let displayValue = value;\n if (this.tooltipFormatter) {\n if (typeof this.tooltipFormatter === 'function') {\n displayValue = this.tooltipFormatter(value, index);\n }\n } else {\n displayValue = typeof value === 'number' ? value.toLocaleString() : value;\n }\n \n // Build tooltip content\n let content = `<strong>${displayValue}</strong>`;\n if (label) {\n content = `${label}<br>${content}`;\n }\n \n this.tooltip.innerHTML = content;\n this.tooltip.style.display = 'block';\n this.updateTooltipPosition(event);\n \n // Highlight bar if in bar chart mode\n if (this.chartType === 'bar') {\n this.highlightBar(index);\n }\n \n // Show crosshair at the hovered position\n if (this.crosshair && this.showCrosshair) {\n const width = this.getActualWidth();\n const barWidth = width / this.data.length;\n const x = (index * barWidth) + (barWidth / 2);\n this.crosshair.setAttribute('x1', x);\n this.crosshair.setAttribute('x2', x);\n this.crosshair.style.display = 'block';\n }\n }\n\n updateTooltipPosition(event) {\n if (!this.tooltip || this.tooltip.style.display === 'none') return;\n \n const rect = this.svg.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n \n // Position tooltip above cursor\n this.tooltip.style.left = `${x}px`;\n this.tooltip.style.top = `${y - 10}px`;\n this.tooltip.style.transform = 'translate(-50%, -100%)';\n }\n\n hideTooltip() {\n if (this.tooltip) {\n this.tooltip.style.display = 'none';\n this.hoveredIndex = -1;\n }\n \n // Remove bar highlight\n if (this.chartType === 'bar') {\n this.unhighlightBars();\n }\n \n // Hide crosshair\n if (this.crosshair) {\n this.crosshair.style.display = 'none';\n }\n }\n\n highlightBar(index) {\n if (!this.svg) return;\n \n // Remove previous highlights\n this.unhighlightBars();\n \n // Highlight the hovered bar\n const bar = this.svg.querySelector(`rect.mini-chart-bar[data-bar-index=\"${index}\"]`);\n if (bar) {\n bar.style.opacity = '0.7';\n }\n }\n\n unhighlightBars() {\n if (!this.svg) return;\n \n const bars = this.svg.querySelectorAll('rect.mini-chart-bar');\n bars.forEach(bar => {\n bar.style.opacity = '1';\n });\n }\n\n // Public API\n setData(data) {\n this.data = data;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setColor(color) {\n this.color = color;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setType(type) {\n if (['line', 'bar'].includes(type)) {\n this.chartType = type;\n if (this.svg) {\n this.renderChart();\n }\n }\n }\n\n resize(width, height) {\n this.width = width;\n this.height = height;\n this.updateDimensions();\n if (this.svg) {\n this.renderChart();\n }\n }\n\n async onBeforeDestroy() {\n // Clean up resize observer\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n await super.onBeforeDestroy();\n }\n}\n","/**\n * MetricsMiniChart - MiniChart with API integration\n * Extends MiniChart to add /api/metrics/fetch support (same API as MetricsChart)\n */\n\nimport MiniChart from './MiniChart.js';\n\nexport default class MetricsMiniChart extends MiniChart {\n constructor(options = {}) {\n super(options);\n \n // API configuration (matching MetricsChart)\n this.endpoint = options.endpoint || '/api/metrics/fetch';\n this.account = options.account || 'global';\n this.granularity = options.granularity || 'hours';\n this.slugs = options.slugs || null; // Single slug or array of slugs\n this.category = options.category || null;\n this.dateStart = options.dateStart || null;\n this.dateEnd = options.dateEnd || null;\n this.defaultDateRange = options.defaultDateRange || '24h';\n \n // State\n this.isLoading = false;\n this.lastFetch = null;\n this.refreshInterval = options.refreshInterval;\n \n // Initialize date range if missing\n if (!this.dateStart || !this.dateEnd) {\n this.setQuickRange(this.defaultDateRange);\n }\n \n // Normalize slugs to array\n if (this.slugs && !Array.isArray(this.slugs)) {\n this.slugs = [this.slugs];\n }\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n \n // Fetch initial data if endpoint provided and no data\n if (this.endpoint && (!this.data || this.data.length === 0)) {\n await this.fetchData();\n }\n \n // Setup auto-refresh if configured\n if (this.refreshInterval && this.endpoint) {\n this.startAutoRefresh();\n }\n }\n\n buildApiParams() {\n const params = {\n granularity: this.granularity,\n account: this.account,\n with_labels: true\n };\n\n // Add slugs\n if (this.slugs && this.slugs.length > 0) {\n this.slugs.forEach(slug => {\n if (!params['slugs[]']) params['slugs[]'] = [];\n params['slugs[]'].push(slug);\n });\n }\n\n if (this.category) {\n params.category = this.category;\n }\n\n // Date range\n if (this.dateStart) {\n params.dr_start = Math.floor(this.dateStart.getTime() / 1000);\n }\n if (this.dateEnd) {\n params.dr_end = Math.floor(this.dateEnd.getTime() / 1000);\n }\n\n // Cache buster\n params._ = Date.now();\n\n return params;\n }\n\n async fetchData() {\n if (!this.endpoint) return;\n \n this.isLoading = true;\n \n try {\n const rest = this.getApp()?.rest;\n if (!rest) {\n throw new Error('No REST client available');\n }\n \n const params = this.buildApiParams();\n const response = await rest.GET(this.endpoint, params);\n \n // Handle Rest standardized response\n if (!response.success) {\n throw new Error(response.message || 'Network error');\n }\n if (!response.data?.status) {\n throw new Error(response.data?.error || 'Server error');\n }\n \n const metricsData = response.data.data;\n this.processMetricsData(metricsData);\n this.lastFetch = new Date();\n \n // Re-render to show updated values\n await this.render();\n \n this.emit('metrics:loaded', { chart: this, data: metricsData, params });\n \n } catch (error) {\n console.error('Failed to fetch metrics:', error);\n this.emit('metrics:error', { chart: this, error });\n } finally {\n this.isLoading = false;\n }\n }\n\n processMetricsData(metricsData) {\n // Expecting: { labels: [...], data: { metric_slug: [values...] } }\n const { data: metrics, labels } = metricsData;\n \n if (!metrics) return;\n \n // Get the first (or only) metric's data\n const metricKeys = Object.keys(metrics);\n if (metricKeys.length === 0) return;\n \n const metricSlug = metricKeys[0];\n const values = metrics[metricSlug];\n \n // Sanitize values\n const sanitizedValues = values.map(val => {\n if (val === null || val === undefined || val === '') return 0;\n return typeof val === 'number' ? val : (parseFloat(val) || 0);\n });\n \n // Update chart data\n this.setData(sanitizedValues);\n }\n\n setQuickRange(range) {\n const now = new Date();\n let startDate;\n\n switch (range) {\n case '1h':\n startDate = new Date(now.getTime() - (60 * 60 * 1000));\n break;\n case '24h':\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n break;\n case '7d':\n startDate = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));\n break;\n case '30d':\n startDate = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));\n break;\n default:\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n }\n\n this.dateStart = startDate;\n this.dateEnd = now;\n }\n\n startAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n }\n \n this.refreshTimer = setInterval(() => {\n this.fetchData();\n }, this.refreshInterval);\n }\n\n stopAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n // Public API\n setGranularity(granularity) {\n this.granularity = granularity;\n return this.fetchData();\n }\n\n setDateRange(startDate, endDate) {\n this.dateStart = new Date(startDate);\n this.dateEnd = new Date(endDate);\n return this.fetchData();\n }\n\n setMetrics(slugs) {\n this.slugs = Array.isArray(slugs) ? slugs : [slugs];\n return this.fetchData();\n }\n\n refresh() {\n return this.fetchData();\n }\n\n async onBeforeDestroy() {\n this.stopAutoRefresh();\n await super.onBeforeDestroy();\n }\n}\n"],"names":["e"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { M as Model, C as Collection, T as ToastService, G as GroupList, d as UserList } from "./ContextMenu-
|
|
2
|
-
import { r as rest, V as View, d as dataFormatter, M as Mustache } from "./WebApp-
|
|
3
|
-
import { P as Page } from "./Page-
|
|
4
|
-
import Dialog from "./Dialog-
|
|
5
|
-
import { F as FormView, a as applyFileDropMixin } from "./FormView-
|
|
1
|
+
import { M as Model, C as Collection, T as ToastService, G as GroupList, d as UserList } from "./ContextMenu-BJlCv6JA.js";
|
|
2
|
+
import { r as rest, V as View, d as dataFormatter, M as Mustache } from "./WebApp-zyQ4x8MK.js";
|
|
3
|
+
import { P as Page } from "./Page-BZA8Inm2.js";
|
|
4
|
+
import Dialog from "./Dialog-CqJQlXoj.js";
|
|
5
|
+
import { F as FormView, a as applyFileDropMixin } from "./FormView-CMdyHmf3.js";
|
|
6
6
|
class S3Bucket extends Model {
|
|
7
7
|
constructor(data = {}) {
|
|
8
8
|
super(data, {
|
|
@@ -7177,4 +7177,4 @@ export {
|
|
|
7177
7177
|
FileList as y,
|
|
7178
7178
|
FileForms as z
|
|
7179
7179
|
};
|
|
7180
|
-
//# sourceMappingURL=ChatView-
|
|
7180
|
+
//# sourceMappingURL=ChatView-BwazIhTw.js.map
|