@perses-dev/timeseries-chart-plugin 0.12.0 → 0.12.1

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.
@@ -1,3 +0,0 @@
1
- "use strict";(self.chunk_TimeSeriesChart=self.chunk_TimeSeriesChart||[]).push([["53"],{3233:function(e,t,l){l.r(t),l.d(t,{TimeSeriesChart:()=>eR});let n={unit:"decimal",shortValues:!0},i={show:!0,label:"",format:n,min:void 0,max:void 0,logBase:void 0},a="Label",o="Min",r="Max",s="Log Base",d={display:"line",lineWidth:1.25,lineStyle:"solid",areaOpacity:0,pointRadius:2.75,connectNulls:!1},u="Line Width",c="slider-line-width",h=.25,p=3,m=.25,v="Line Style",g="Area Opacity",x="slider-area-opacity",f=0,y=1,b=.05,j="Stack Series",C="Connect Nulls",A={none:{label:"None"},all:{label:"All"}},S=Object.entries(A).map(e=>{let[t,l]=e;return{id:t,...l}}),M={solid:{label:"Solid"},dashed:{label:"Dashes"},dotted:{label:"Dots"}},w={none:{label:"None",log:void 0},2:{label:"2",log:2},10:{label:"10",log:10}},O=Object.entries(w).map(e=>{let[t,l]=e;return{id:t,...l}});var E=l(62540),T=l(7013),L=l(38662),k=l(43349),I=l(36603),D=l(61375),R=l(31729),_=l(40704),N=l(68003);function $(e){let{value:t,onChange:l}=e,n=t.stack??"none",i=A[n];return(0,E.jsxs)(k.OptionsEditorGroup,{title:"Visual",children:[(0,E.jsx)(k.OptionsEditorControl,{label:j,control:(0,E.jsx)(k.SettingsAutocomplete,{value:{...i,id:n},options:S,onChange:(e,n)=>{let i={...t,stack:"none"===n.id?void 0:n.id};"all"!==n.id||t.areaOpacity||(i.areaOpacity=.3),l(i)},disabled:void 0===t,disableClearable:!0})}),(0,E.jsx)(k.OptionsEditorControl,{label:"Display",control:(0,E.jsxs)(D.A,{color:"primary",exclusive:!0,value:t.display??"line",onChange:(e,n)=>{l({...t,display:n})},children:[(0,E.jsx)(R.A,{value:"line",selected:void 0===t.display||"line"===t.display,"aria-label":"display line series",children:"Line"}),(0,E.jsx)(R.A,{value:"bar","aria-label":"display bar series",children:"Bar"})]})}),"line"===t.display&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(k.OptionsEditorControl,{label:u,control:(0,E.jsx)(_.Ay,{"data-testid":c,value:t.lineWidth??1.25,valueLabelDisplay:"auto",step:m,marks:!0,min:h,max:p,onChange:(e,n)=>{let i=Array.isArray(n)?n[0]:n,a=void 0!==i?i+1.5:2.75;l((0,L.jM)(t,e=>{e.lineWidth=i,e.pointRadius=a}))}})}),(0,E.jsx)(k.OptionsEditorControl,{label:v,control:(0,E.jsx)(D.A,{color:"primary",exclusive:!0,value:t.lineStyle??"solid",onChange:(e,n)=>{l({...t,lineStyle:n})},children:Object.entries(M).map(e=>{let[t,l]=e;return(0,E.jsx)(R.A,{value:t,"aria-label":`${t} line style`,children:l.label},t)})})}),(0,E.jsx)(k.OptionsEditorControl,{label:g,control:(0,E.jsx)(_.Ay,{"data-testid":x,value:t.areaOpacity??0,valueLabelDisplay:"auto",step:b,marks:!0,min:f,max:y,onChange:(e,n)=>{let i=Array.isArray(n)?n[0]:n;l((0,L.jM)(t,e=>{e.areaOpacity=i}))}})}),(0,E.jsx)(k.OptionsEditorControl,{label:C,control:(0,E.jsx)(N.A,{checked:t.connectNulls??!1,onChange:e=>{l({...t,connectNulls:e.target.checked})}})})]})]})}var F=l(93648);function V(e){let{value:t,onChange:l}=e,d=t.logBase?w[t.logBase]:void 0;return(0,E.jsxs)(k.OptionsEditorGroup,{title:"Y Axis",children:[(0,E.jsx)(k.OptionsEditorControl,{label:"Show",control:(0,E.jsx)(N.A,{checked:t.show??i.show,onChange:e=>{l({...t,show:e.target.checked})}})}),(0,E.jsx)(k.FormatControls,{value:t.format??n,onChange:e=>l({...t,format:e})}),(0,E.jsx)(k.OptionsEditorControl,{label:s,control:(0,E.jsx)(k.SettingsAutocomplete,{value:{...d,id:(null==d?void 0:d.label)??"None"},options:O,onChange:(e,n)=>{l({...t,logBase:n.log??void 0})},disabled:void 0===t,disableClearable:!0})}),(0,E.jsx)(k.OptionsEditorControl,{label:a,control:(0,E.jsx)(F.A,{value:t.label??"",inputProps:{"aria-label":"enter y axis label"},onChange:e=>l({...t,label:e.target.value}),placeholder:"Default"})}),(0,E.jsx)(k.OptionsEditorControl,{label:o,control:(0,E.jsx)(F.A,{type:"number",value:t.min??"",onChange:e=>{let n=e.target.value?Number(e.target.value):void 0;l({...t,min:n})},placeholder:"Default"})}),(0,E.jsx)(k.OptionsEditorControl,{label:r,control:(0,E.jsx)(F.A,{type:"number",value:t.max??"",onChange:e=>{let n=e.target.value?Number(e.target.value):void 0;l({...t,max:n})},placeholder:"Default"})})]})}var P=l(315),B=l(88091),G=l(97653),U=l(74628),q=l(47095),z=l(30145),W=l(56599),H=l(70451),Y=l(86067),Q=l(86742),Z=l(7800);let X="#555";function K(e){let{querySettings:{queryIndex:t,colorMode:l,colorValue:n,lineStyle:i,areaOpacity:a,format:o},availableQueryIndexes:r,onQueryIndexChange:s,onColorModeChange:d,onColorValueChange:u,onLineStyleChange:c,onAreaOpacityChange:h,onDelete:p,inputRef:m,onAddColor:v,onRemoveColor:g,onAddLineStyle:x,onRemoveLineStyle:f,onAddAreaOpacity:y,onRemoveAreaOpacity:b,onAddUnit:j,onRemoveUnit:C,onUnitChange:A}=e,S=r.concat(t).sort((e,t)=>e-t),[w,O]=(0,H.useState)(null),T=(0,H.useMemo)(()=>{let e=[];return l||e.push({key:"color",label:"Color",action:v}),i||e.push({key:"lineStyle",label:"Line Style",action:x}),void 0===a&&e.push({key:"opacity",label:"Opacity",action:y}),void 0===o&&e.push({key:"unit",label:"Unit",action:j}),e},[l,i,a,o,v,x,y,j]),L=()=>{O(null)};return(0,E.jsx)(P.A,{sx:{borderBottom:"1px solid",borderColor:"divider",borderRadius:1,p:2},children:(0,E.jsxs)(P.A,{direction:"row",alignItems:"center",sx:{flexWrap:"wrap",gap:2},children:[(0,E.jsx)(F.A,{select:!0,inputRef:m,value:t,label:"Query",onChange:s,sx:{minWidth:"75px"},children:S.map(e=>(0,E.jsxs)(G.A,{value:e,children:["#",e+1]},`query-${e}`))}),l&&(0,E.jsxs)(J,{label:"Color",onRemove:g,children:[(0,E.jsxs)(F.A,{select:!0,value:l,onChange:d,size:"small",sx:{flexGrow:1},children:[(0,E.jsx)(G.A,{value:"fixed-single",children:"Fixed (single)"}),(0,E.jsx)(G.A,{value:"fixed",children:"Fixed"})]}),(0,E.jsx)(k.OptionsColorPicker,{label:`Query n\xb0${t+1}`,color:n||X,onColorChange:u})]}),i&&(0,E.jsxs)(J,{label:"Line Style",onRemove:f,children:[(0,E.jsx)(D.A,{color:"primary",exclusive:!0,value:i,onChange:(e,t)=>{null!==t&&c(t)},size:"small",children:Object.entries(M).map(e=>{let[t,l]=e;return(0,E.jsx)(R.A,{value:t,"aria-label":`${t} line style`,children:l.label},t)})}),(0,E.jsx)(U.A,{sx:{flexGrow:1}})]}),void 0!==a&&(0,E.jsxs)(J,{label:"Opacity",onRemove:b,children:[(0,E.jsx)(U.A,{}),(0,E.jsx)(_.Ay,{value:a,valueLabelDisplay:"auto",step:.05,marks:!0,min:0,max:1,onChange:h,sx:{flexGrow:1}})]}),void 0!==o&&(0,E.jsx)(J,{label:"Unit",onRemove:C,children:(0,E.jsx)(U.A,{sx:{minWidth:"180px"},children:(0,E.jsx)(k.UnitSelector,{value:o,onChange:A})})}),T.length>0&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(q.A,{onClick:e=>{1===T.length&&T[0]?T[0].action():O(e.currentTarget)},"aria-label":"Add option",children:(0,E.jsx)(Q.default,{})}),(0,E.jsx)(z.A,{anchorEl:w,open:!!w,onClose:L,anchorOrigin:{vertical:"bottom",horizontal:"left"},children:T.map(e=>(0,E.jsxs)(G.A,{onClick:()=>{(0,e.action)(),L()},sx:{minWidth:"120px"},children:[(0,E.jsx)(Q.default,{sx:{mr:1,fontSize:"1rem"}}),e.label]},e.key))})]}),(0,E.jsx)(U.A,{sx:{flexGrow:1}}),(0,E.jsx)(q.A,{"aria-label":`delete settings for query n\xb0${t+1}`,onClick:p,children:(0,E.jsx)(Y.default,{})})]})})}function J(e){let{label:t,children:l,onRemove:n}=e,i=(0,W.A)();return(0,E.jsxs)(U.A,{sx:{position:"relative",minWidth:"250px"},children:[(0,E.jsx)(B.A,{variant:"caption",sx:{position:"absolute",top:-8,left:12,backgroundColor:i.palette.background.code,px:.5,color:"text.secondary",zIndex:1},children:t}),(0,E.jsxs)(P.A,{direction:"row",alignItems:"center",spacing:1,sx:{border:"1px solid",borderColor:"divider",borderRadius:1,p:1},children:[l,(0,E.jsx)(q.A,{size:"small",onClick:n,"aria-label":`Remove ${t}`,children:(0,E.jsx)(Z.default,{})})]})]})}var ee=l(25632),et=l.n(ee),el=l(3967),en=l(87680),ei=l(99415),ea=l(12826);function eo(e){let t=Math.floor(Math.log10(Math.abs(e)));return Math.floor(e/Math.pow(10,t))*Math.pow(10,t)}var er=l(92959);let es=new er.A({hue:{min:20,max:360}}),ed=new er.A({hue:{min:0,max:20}}),eu={};var ec=l(18264),eh=l.n(ec),ep=l(63682),em=l(74653),ev=l(62707),eg=l(31373),ex=l(59738),ef=l(90652),ey=l(61305),eb=l(64404),ej=l(28502),eC=l(48683),eA=l(72106),eS=l(40988),eM=l(55875),ew=l(37573);(0,em.Y)([ev.a,eg.a,ex.a,ef.a,ey.a,eb.a,ej.a,eC.a,eA.a,eS.a,eM.a,ew.a]);let eO=(0,H.forwardRef)(function(e,t){var l;let n,{height:i,data:a,seriesMapping:o,timeScale:r,yAxis:s,format:d,seriesFormatMap:u,grid:c,isStackedBar:h=!1,tooltipConfig:p=k.DEFAULT_TOOLTIP_CONFIG,noDataVariant:m="message",syncGroup:v,onDataZoom:g,onDoubleClick:x,__experimentalEChartsOptionsOverride:f}=e,{chartsTheme:y,enablePinning:b,enableSyncGrouping:j,lastTooltipPinnedCoords:C,setLastTooltipPinnedCoords:A}=(0,k.useChartsContext)(),S=p.enablePinning&&b,M=(0,H.useRef)(),[w,O]=(0,H.useState)(!0),[T,L]=(0,H.useState)(null),[I,D]=(0,H.useState)(null),[R,_]=(0,H.useState)(!1),[N,$]=(0,H.useState)(0),{timeZone:F}=(0,k.useTimeZone)();if(void 0===r){let e=(0,ei.l$)(a);if(void 0===e){let e=new Date,t=new Date(e);t.setFullYear(e.getFullYear()-5);let l=e.getTime(),i=t.getTime();n={startMs:i,endMs:l,stepMs:1,rangeMs:l-i}}else n=e}else n=r;(0,H.useImperativeHandle)(t,()=>({highlightSeries(e){let{name:t}=e;M.current&&M.current.dispatchAction({type:"highlight",seriesId:t})},clearHighlightedSeries:()=>{M.current&&(0,k.clearHighlightedSeries)(M.current)}}),[]);let V=(0,H.useMemo)(()=>({datazoom:e=>{if(void 0===g&&setTimeout(()=>{L(null)},10),void 0===g||void 0===e.batch[0])return;let t=e.batch[0].startValue,l=e.batch[0].endValue;void 0!==t&&void 0!==l&&g({start:t,end:l})},finished:()=>{void 0!==M.current&&(0,k.enableDataZoom)(M.current)}}),[g,L]),{noDataOption:P}=y,B=(0,H.useMemo)(()=>{if(null===a||0===a.length&&"message"===m)return P;let e=[],t="local"===F;a.map((l,n)=>{let i=l.values.map(e=>{let[l,n]=e;return[t?l:(0,ep.toZonedTime)(l,F),null===n?"-":n]});e.push({id:n,source:[...i],dimensions:["time","value"]})});let l={dataset:e,series:b&&null!==I?[...o,I]:o,xAxis:{type:"time",min:t?n.startMs:(0,ep.toZonedTime)(n.startMs,F),max:t?n.endMs:(0,ep.toZonedTime)(n.endMs,F),axisLabel:{hideOverlap:!0,formatter:(0,k.getFormattedAxisLabel)(n.rangeMs??0)},axisPointer:{snap:!1}},yAxis:Array.isArray(s)?s:(0,k.getFormattedAxis)(s,d),animation:!1,tooltip:{show:!0,showContent:h,trigger:h?"item":"axis",appendToBody:h},axisPointer:{type:"line",z:0,triggerEmphasis:!1,triggerTooltip:!1,snap:!1},toolbox:{feature:{dataZoom:{icon:null,yAxisIndex:"none"}}},grid:c};return f?f(l):l},[a,o,n,s,d,c,P,f,m,F,h,b,I]);return(0,H.useEffect)(()=>{null===T||null===C||eh()(C,T)||(L(null),null!==T&&null!==I&&D(null))},[C,o]),(0,E.jsxs)(U.A,{style:{height:i},onClick:e=>{let t=e.ctrlKey||e.metaKey;t&&e.preventDefault();let l=(0,k.getPointInGrid)(e.nativeEvent.offsetX,e.nativeEvent.offsetY,M.current);if(null!==l&&S&&e.target instanceof HTMLCanvasElement){let n={page:{x:e.pageX,y:e.pageY},client:{x:e.clientX,y:e.clientY},plotCanvas:{x:e.nativeEvent.offsetX,y:e.nativeEvent.offsetY},target:e.target};L(e=>null===e?n:(D(null),null)),D(e=>{if(null!==e)return null;{var t;let e=l[0],n=null==(t=a[0])?void 0:t.values,i=(0,k.getClosestTimestamp)(n,e);return et()({},k.DEFAULT_PINNED_CROSSHAIR,{markLine:{data:[{xAxis:i}]}})}}),t||A(n)}},onMouseDown:e=>{let{clientX:t}=e;_(!0),$(t)},onMouseMove:e=>{if(!(e.target instanceof HTMLCanvasElement))return;let{clientX:t}=e;R&&t-N>0&&O(!1)},onMouseUp:()=>{_(!1),$(0),O(!0)},onMouseLeave:()=>{null===T&&O(!1),void 0!==M.current&&(0,k.clearHighlightedSeries)(M.current)},onMouseEnter:()=>{O(!0),void 0!==M.current&&(0,k.enableDataZoom)(M.current)},onDoubleClick:e=>{L(null),void 0===x?void 0!==M.current&&(0,k.restoreChart)(M.current):x(e)},children:[!0===w&&(null==(l=B.tooltip)?void 0:l.showContent)===!1&&!0!==p.hidden&&(0,E.jsx)(k.TimeChartTooltip,{containerId:y.tooltipPortalContainerId,chartRef:M,data:a,seriesMapping:o,wrapLabels:p.wrapLabels,enablePinning:S,pinnedPos:T,format:d,seriesFormatMap:u,onUnpinClick:()=>{L(null),D(null)}}),(0,E.jsx)(k.EChart,{sx:{width:"100%",height:"100%"},option:B,theme:y.echartsTheme,onEvents:V,_instance:M,syncGroup:j?v:void 0})]})});var eE=l(54042);let eT=e=>!!(e&&"object"==typeof e&&"series"in e&&Array.isArray(e.series)&&e.series.length>0),eL=(e,t)=>{let l=e.formattedName||e.name;if(l&&l!==`Series ${t+1}`||(l=e.legendName||e.displayName||e.legend||e.name||""),(!l||l===e.name)&&e.labels){let n=e.labels,i={...n},a=i.__name__;delete i.__name__;let o=Object.entries(i).filter(e=>{let[t]=e;return null!=t&&""!==t}).map(e=>{let[t,l]=e;return`${t}="${l}"`}).join(", ");l=a&&o?`${a}{${o}}`:a||(o?`{${o}}`:n.job||n.instance||n.metric||`Series ${t+1}`)}return l&&""!==l.trim()||(l=`Series ${t+1}`),l},ek=e=>e.replace(/[,"\n\r]/g,"_").replace(/\s+/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"").substring(0,255),eI=e=>{let t;if("string"==typeof e){let l=new Date(e);if(isNaN(l.getTime()))return e;t=l.getTime()}else t=e>1e10?e:1e3*e;let l=new Date(t);return isNaN(l.getTime())?new Date(t).toISOString():l.toISOString()},eD=e=>{if(null==e)return"";let t=String(e);return t.includes(",")||t.includes('"')||t.includes("\n")||t.includes("\r")?`"${t.replace(/"/g,'""')}"`:t},eR={PanelComponent:function(e){var t;let{spec:{thresholds:l,yAxis:a,tooltip:o,querySettings:r},contentDimensions:s,queryResults:u}=e,c=(0,k.useChartsTheme)(),h=(0,W.A)(),p=(0,k.useId)("time-series-panel"),m=(0,H.useRef)(null),v=c.echartsTheme.color,g=c.container.padding.default,x=s?{width:s.width-2*g,height:s.height-2*g}:void 0,f=(0,H.useMemo)(()=>e.spec.legend&&(0,I.validateLegendSpec)(e.spec.legend)?et()({},el.yf,e.spec.legend):void 0,[e.spec.legend]),y=(null==(t=e.spec.yAxis)?void 0:t.format)??n,b=(0,H.useMemo)(()=>et()({},d,e.spec.visual),[e.spec.visual]),j=(0,H.useMemo)(()=>(function(){let e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};e=void 0!==t.logBase?void 0:(null==t?void 0:t.min)!==void 0?t.min:e=>e.min>=0&&e.min<=1?0:e.min>0?eo(.8*e.min):eo(1.2*e.min);let l={show:(null==t?void 0:t.show)??i.show,min:e,max:null==t?void 0:t.max};return void 0!==t.logBase?{...l,type:"log",logBase:t.logBase}:l})(a),[a]),{additionalFormats:C,formatToYAxisIndex:A,seriesFormatMap:S}=(0,H.useMemo)(()=>{let e=(null==y?void 0:y.unit)??"decimal",t=[],l=new Map,n=new Map;for(let n of(l.set(e,0),r??[])){var i;if((null==(i=n.format)?void 0:i.unit)&&n.format.unit!==e){let e=n.format.unit;l.has(e)||(l.set(e,1+t.length),t.push(n.format))}}return{additionalFormats:t,formatToYAxisIndex:l,seriesFormatMap:n}},[y,r]),[M,w]=(0,H.useState)("ALL"),[O,T]=(0,H.useState)(),{setTimeRange:L}=(0,I.useTimeRange)(),{timeScale:D,timeChartData:R,timeSeriesMapping:_,legendItems:N,seriesFormatMap:$,maxValuesByFormat:F}=(0,H.useMemo)(()=>{let e,t=(e=u.map(e=>e.data),(0,ei.l$)(e));if(void 0===t)return{timeChartData:[],timeSeriesMapping:[],seriesFormatMap:new Map,maxValuesByFormat:new Map};let n=[],i=[],o=[],s=new Map,d=0;for(let e=0;e<u.length;e++){let l,a=u[e];for(let t of r??[])t.queryIndex===e&&(l=t);if(a)for(let r=0;r<a.data.series.length;r++){var m,g,x;let c=a.data.series[r];if(void 0===c)return{timeChartData:[],timeSeriesMapping:[],legendItems:[]};let y=c.formattedName??c.name,j=function(e){var t,l,n;let{categoricalPalette:i,visual:a,muiPrimaryColor:o,seriesName:r,seriesIndex:s,querySettings:d,queryHasMultipleResults:u}=e;if(d){if("fixed"===d.colorMode&&d.colorValue)return d.colorValue;else if("fixed-single"===d.colorMode&&!u&&d.colorValue)return d.colorValue}let c=Array.isArray(i)&&i[0]?i[0]:o;return(null==(t=a.palette)?void 0:t.mode)==="categorical"?function(e,t,l){if(void 0===e)return l;let n=e.length??1;return e[t%n]??l}(i,s,c):(l=r,n=c,function(e){var t;let l,n;return t=e.toLowerCase().includes("error"),(n=eu[l=`${e}_____${t}`])||(n=function(e,t){let[l,n,i]=t?ed.hsl(e):es.hsl(e),a=`${(100*n).toFixed(0)}%`,o=`${(100*i).toFixed(0)}%`;return`hsla(${l.toFixed(2)},${a},${o},0.9)`}(e,t),eu[l]=n),n}(l)??n)}({categoricalPalette:v,visual:b,muiPrimaryColor:h.palette.primary.main,seriesName:y,seriesIndex:d,querySettings:l,queryHasMultipleResults:((null==(x=u[e])||null==(g=x.data)||null==(m=g.series)?void 0:m.length)??0)>1}),C=p+c.name+d,w=(null==f?void 0:f.values)?(0,en.pG)(c.values,f.values):void 0,O="ALL"===M;if(!O&&M[C]||O){let e=i.length,n=null==l?void 0:l.format,a=(null==n?void 0:n.unit)?A.get(n.unit)??0:0;if(o.push(function(e,t,l,n,i,a,o,r){let s=n.lineWidth??1.25,d=n.pointRadius??2.75,u=i.rangeMs<=9e5;return("always"===n.showPoints&&(u=!0),"bar"===n.display)?{type:"bar",id:e,datasetIndex:t,name:l,color:a,stack:"all"===n.stack?n.stack:void 0,yAxisIndex:r,label:{show:!1}}:{type:"line",id:e,datasetIndex:t,name:l,connectNulls:n.connectNulls??!1,color:a,stack:"all"===n.stack?n.stack:void 0,yAxisIndex:r,sampling:"lttb",progressiveThreshold:k.OPTIMIZED_MODE_SERIES_LIMIT,showSymbol:u,showAllSymbol:!0,symbolSize:d,lineStyle:{width:s,type:(null==o?void 0:o.lineStyle)??n.lineStyle},areaStyle:{opacity:(null==o?void 0:o.areaOpacity)??n.areaOpacity??0},emphasis:{focus:"series",disabled:void 0!==n.areaOpacity&&n.areaOpacity>0,lineStyle:{width:s+1,opacity:1,type:n.lineStyle}},selectedMode:"single",select:{itemStyle:{borderColor:a,borderWidth:d+.5}},blur:{lineStyle:{width:s,opacity:.5,type:n.lineStyle}}}}(C,e,y,b,t,j,l,a)),n){S.set(C,n);let e=n.unit;if(e){let t=Math.max(...c.values.map(e=>Math.abs(e[1]??0)));t>(s.get(e)??0)&&s.set(e,t)}}i.push({name:y,values:(0,ei.rT)(c,t)})}f&&n&&n.push({id:C,label:y,color:j,data:w}),d++}}if(l&&l.steps){let e=c.thresholds,n=l.defaultColor??e.defaultColor;l.steps.forEach((r,s)=>{var u,c,h,p,m;let v,g,x,f=e.palette[s]??n,y={color:r.color??f,value:"percent"===l.mode?(u=r.value,c=null==a?void 0:a.max,h=null==a?void 0:a.min,g=c??(v=0,(p=i).length&&void 0!==p[0]&&(null==(m=p[0])?void 0:m.values)?p.forEach(e=>{e.values.forEach(e=>{let[t,l]=e;"number"==typeof l&&l>v&&(v=l)})}):p.forEach(e=>{void 0!==e.data&&e.data.forEach(e=>{"number"==typeof e&&e>v&&(v=e)})}),v),u/100*(g-(x=h??0))+x):r.value},b=r.name??`Threshold ${s+1}`,j=[],C=t.startMs;for(;C<=t.endMs;)j.push([C,y.value]),C+=15e3;i.push({name:b,values:j}),o.push({type:"line",name:b,id:b,datasetId:b,datasetIndex:d,color:y.color,label:{show:!1},lineStyle:{type:"dashed",width:2},emphasis:{focus:"series",lineStyle:{width:2.5}},blur:{lineStyle:{opacity:.5}}}),d++})}return{timeScale:t,timeChartData:i,timeSeriesMapping:o,legendItems:n,seriesFormatMap:S,maxValuesByFormat:s}},[u,l,M,f,b,r,null==a?void 0:a.max,null==a?void 0:a.min,v,p,c.thresholds,h.palette.primary.main,A,S]),V=(0,H.useMemo)(()=>{if(0===C.length)return;let e=C.map(e=>{let t=e.unit;return t?(null==F?void 0:F.get(t))??1e3:1e3});return(0,k.getFormattedMultipleYAxes)(j,y,C,e)},[j,y,C,F]),P=(0,H.useMemo)(()=>(null==f?void 0:f.values)?I.legendValues.reduce((e,t)=>{var l;let n=I.LEGEND_VALUE_CONFIG[t];return n&&(null==f||null==(l=f.values)?void 0:l.includes(t))&&e.push({accessorKey:`data.${t}`,header:n.label,headerDescription:n.description,width:72,align:"right",cell:e=>{let{getValue:t}=e,l=t();return"number"==typeof l&&y?(0,ea.Fl)(l,y):l},cellDescription:!0,enableSorting:!0}),e},[]):[],[null==f?void 0:f.values,y]),B=(0,H.useMemo)(()=>!1===j.show?{left:0,right:0,bottom:30,containLabel:!1}:{left:a&&a.label?30:20,right:C.length>0?10:20,bottom:0,containLabel:!0},[j.show,a,C.length]);if(void 0===x)return null;let G=e=>{L({start:new Date(e.start),end:new Date(e.end)})},q="bar"===b.display&&"all"===b.stack,z=!0;q?z=!1:(null==o?void 0:o.enablePinning)!==void 0&&(z=o.enablePinning);let Y={...k.DEFAULT_TOOLTIP_CONFIG,enablePinning:z};return(0,E.jsx)(U.A,{sx:{padding:`${g}px`},children:(0,E.jsx)(k.ContentWithLegend,{width:x.width,height:x.height,minChildrenHeight:50,legendSize:null==f?void 0:f.size,legendProps:f&&{options:f,data:N||[],selectedItems:M,onSelectedItemsChange:w,tableProps:{columns:P,sorting:O,onSortingChange:T},onItemMouseOver:(e,t)=>{var l;let{id:n}=t;null==(l=m.current)||l.highlightSeries({name:n})},onItemMouseOut:()=>{var e;null==(e=m.current)||e.clearHighlightedSeries()}},children:e=>{let{height:t,width:l}=e;return(0,E.jsxs)(U.A,{style:{height:t,width:l},children:[a&&a.show&&a.label&&(0,E.jsx)(k.YAxisLabel,{name:a.label,height:t}),(0,E.jsx)(eO,{ref:m,height:t,data:R,seriesMapping:_,timeScale:D,yAxis:V??j,format:y,seriesFormatMap:$,grid:B,isStackedBar:q,tooltipConfig:Y,syncGroup:"default-panel-group",onDataZoom:G,noDataVariant:!R.length&&N&&N.length>0?"chart":"message"})]})}})})},supportedQueryTypes:["TimeSeriesQuery"],panelOptionsEditorComponents:[{label:"General Settings",content:function(e){let{onChange:t,value:l}=e;return(0,E.jsxs)(k.OptionsEditorGrid,{children:[(0,E.jsxs)(k.OptionsEditorColumn,{children:[(0,E.jsx)(I.LegendOptionsEditor,{calculation:"aggregation",value:l.legend,onChange:e=>{t((0,L.jM)(l,t=>{t.legend=e}))}}),(0,E.jsx)($,{value:l.visual??d,onChange:e=>{t((0,L.jM)(l,t=>{t.visual=e}))}})]}),(0,E.jsx)(k.OptionsEditorColumn,{children:(0,E.jsx)(V,{value:l.yAxis??i,onChange:e=>{t((0,L.jM)(l,t=>{t.yAxis=e}))}})}),(0,E.jsxs)(k.OptionsEditorColumn,{children:[(0,E.jsx)(k.ThresholdsEditor,{hideDefault:!0,thresholds:l.thresholds,onChange:e=>{t((0,L.jM)(l,t=>{t.thresholds=e}))}}),(0,E.jsx)(k.OptionsEditorGroup,{title:"Reset Settings",children:(0,E.jsx)(T.A,{variant:"outlined",color:"secondary",onClick:()=>{t((0,L.jM)(l,e=>{e.yAxis=void 0,e.legend=void 0,e.visual=void 0,e.thresholds=void 0}))},children:"Reset To Defaults"})})]})]})}},{label:"Query Settings",content:function(e){let{onChange:t,value:l}=e,n=l.querySettings,i=e=>{t((0,L.jM)(l,t=>{t.querySettings=e}))},a=(0,H.useRef)(null),o=(0,H.useRef)(!1);(0,H.useEffect)(()=>{var e;a.current&&o.current&&(null==(e=a.current)||e.focus(),o.current=!1)},[null==n?void 0:n.length]);let r=(e,t)=>{void 0!==n&&i((0,L.jM)(n,l=>{let n=l[e];n&&t(n)}))},s=(0,I.useQueryCountContext)(),d=(0,H.useMemo)(()=>{let e=(null==n?void 0:n.map(e=>e.queryIndex))??[];return Array.from({length:s},(e,t)=>t).filter((t,l)=>!e.includes(l))},[n,s]),u=(0,H.useMemo)(()=>d[0]??-1,[d]),c={queryIndex:u};return(0,E.jsxs)(P.A,{children:[0===s?(0,E.jsx)(B.A,{mb:2,fontStyle:"italic",children:"No query defined"}):(null==n?void 0:n.length)&&n.map((e,t)=>(0,E.jsx)(K,{inputRef:t===n.length-1?a:void 0,querySettings:e,availableQueryIndexes:d,onQueryIndexChange:e=>{void 0!==n&&i((0,L.jM)(n,l=>{let n=null==l?void 0:l[t];n&&(n.queryIndex=parseInt(e.target.value))}))},onColorModeChange:e=>{void 0!==n&&i((0,L.jM)(n,l=>{if(void 0!==l){let n=l[t];if(n){let t=e.target.value;t?n.colorMode=t:(n.colorMode=void 0,n.colorValue=void 0)}}}))},onColorValueChange:e=>{void 0!==n&&i((0,L.jM)(n,l=>{if(void 0!==l){let n=l[t];n&&(n.colorValue=e)}}))},onLineStyleChange:e=>{void 0!==n&&i((0,L.jM)(n,l=>{if(void 0!==l){let n=l[t];n&&(n.lineStyle=e)}}))},onAreaOpacityChange:(e,l)=>{let a;return a=Array.isArray(l)?l[0]:l,void(void 0!==n&&i((0,L.jM)(n,e=>{if(void 0!==e){let l=e[t];l&&(l.areaOpacity=a)}})))},onDelete:()=>{void 0!==n&&i((0,L.jM)(n,e=>{e.splice(t,1)}))},onAddColor:()=>{r(t,e=>{e.colorMode="fixed-single",e.colorValue=X})},onRemoveColor:()=>{r(t,e=>{e.colorMode=void 0,e.colorValue=void 0})},onAddLineStyle:()=>{r(t,e=>{e.lineStyle="solid"})},onRemoveLineStyle:()=>{r(t,e=>{e.lineStyle=void 0})},onAddAreaOpacity:()=>{r(t,e=>{e.areaOpacity=0})},onRemoveAreaOpacity:()=>{r(t,e=>{e.areaOpacity=void 0})},onAddUnit:()=>{r(t,e=>{e.format={unit:"decimal"}})},onRemoveUnit:()=>{r(t,e=>{e.format=void 0})},onUnitChange:e=>{r(t,t=>{t.format=e})}},t)),s>0&&-1!==u&&(0,E.jsx)(T.A,{variant:"contained",startIcon:(0,E.jsx)(Q.default,{}),sx:{marginTop:1},onClick:()=>{o.current=!0,void 0===n?i([c]):i((0,L.jM)(n,e=>{e.push(c)}))},children:"Add Query Settings"})]})}}],createInitialOptions:function(){return{}},actions:[{component:e=>{let{queryResults:t,definition:l}=e,n=(0,H.useMemo)(()=>(e=>{let t,l,n;if(!e||0===e.length)return;let i=[];if(e.forEach(e=>{if((null==e?void 0:e.data)&&"object"==typeof e.data&&"series"in e.data){let a=e.data;a.series&&Array.isArray(a.series)&&a.series.length>0&&(i.push(...a.series),!t&&a.timeRange&&(t=a.timeRange),!l&&a.stepMs&&(l=a.stepMs),!n&&a.metadata&&(n=a.metadata))}}),i.length>0)return{series:i,timeRange:t,stepMs:l,metadata:n}})(t),[t]),i=(0,H.useMemo)(()=>eT(n),[n]),a=(0,H.useCallback)(()=>{if(n&&i)try{var e,t;let i=(null==l||null==(t=l.spec)||null==(e=t.display)?void 0:e.name)||"Time Series Data",a=(e=>{let{data:t}=e;if(!eT(t))return console.warn("No valid data found to export to CSV."),new Blob([""],{type:"text/csv;charset=utf-8"});let l="",n={},i=[],a=0;for(let e=0;e<t.series.length;e++){let l=t.series[e];if(!l||!Array.isArray(l.values)||0===l.values.length)continue;let o=eL(l,e),r=ek(o),s={legendName:o,columnName:r||`Series_${e+1}`,originalName:l.name||""};i.push(s),a++;for(let e=0;e<l.values.length;e++){let t,i,a=l.values[e];if(Array.isArray(a)&&a.length>=2)t=a[0],i=a[1];else{if("object"!=typeof a||null===a||!("timestamp"in a)||!("value"in a))continue;t=a.timestamp,i=a.value}if(null==i)continue;let o=eI(t);n[o]||(n[o]={}),n[o][s.columnName]=i}}if(0===a||0===i.length)return console.warn("No valid data found to export to CSV."),new Blob([""],{type:"text/csv;charset=utf-8"});if(0===Object.keys(n).length)return console.warn("No valid timestamp data found to export to CSV."),new Blob([""],{type:"text/csv;charset=utf-8"});let o=i.map(e=>e.columnName);for(let e of(l+=`DateTime,${o.join(",")}
2
- `,Object.keys(n).sort((e,t)=>new Date(e).getTime()-new Date(t).getTime()))){let t=n[e],i=[];if(t){for(let e of o){let l=t[e];i.push(eD(l))}l+=`${eD(e)},${i.join(",")}
3
- `}}return new Blob([l],{type:"text/csv;charset=utf-8"})})({data:n}),o=i.replace(/[<>:"/\\|?*]/g," ").trim().split(/\s+/).filter(e=>e.length>0).map((e,t)=>0===t?e.toLowerCase():e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(""),r=`${o}_data.csv`,s=document.createElement("a");s.href=URL.createObjectURL(a),s.download=r,document.body.appendChild(s),s.click(),document.body.removeChild(s),URL.revokeObjectURL(s.href)}catch(e){console.error("Time series export failed:",e)}},[n,i,l]);return i?(0,E.jsx)(k.InfoTooltip,{description:"Export as CSV",children:(0,E.jsx)(q.A,{size:"small",onClick:a,"aria-label":"Export time series data as CSV",children:(0,E.jsx)(eE.default,{fontSize:"inherit"})})}):null},location:"header"}]}}}]);
@@ -1,39 +0,0 @@
1
- export interface SeriesDataPoint {
2
- timestamp: number | string;
3
- value: unknown;
4
- }
5
- export interface DataSeries {
6
- name?: string;
7
- formattedName?: string;
8
- legendName?: string;
9
- displayName?: string;
10
- legend?: string;
11
- labels?: Record<string, string>;
12
- values: Array<[number | string, unknown]> | SeriesDataPoint[];
13
- }
14
- export interface ExportableData {
15
- series: DataSeries[];
16
- timeRange?: {
17
- start: string | number;
18
- end: string | number;
19
- };
20
- stepMs?: number;
21
- metadata?: Record<string, unknown>;
22
- }
23
- export declare const isExportableData: (data: unknown) => data is ExportableData;
24
- export interface QueryDataInput {
25
- data?: unknown;
26
- error?: unknown;
27
- isFetching?: boolean;
28
- }
29
- export declare const extractExportableData: (queryResults: QueryDataInput[]) => ExportableData | undefined;
30
- export declare const formatLegendName: (series: DataSeries, seriesIndex: number) => string;
31
- export declare const sanitizeColumnName: (name: string) => string;
32
- export declare const sanitizeFilename: (filename: string) => string;
33
- export declare const formatTimestampISO: (timestamp: number | string) => string;
34
- export declare const escapeCsvValue: (value: unknown) => string;
35
- export interface ExportDataOptions {
36
- data: ExportableData;
37
- }
38
- export declare const exportDataAsCSV: ({ data }: ExportDataOptions) => Blob;
39
- //# sourceMappingURL=CSVExportUtils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CSVExportUtils.d.ts","sourceRoot":"","sources":["../../src/CSVExportUtils.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,eAAe,EAAE,CAAC;CAC/D;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE;QACV,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QACvB,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACtB,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,OAAO,KAAG,IAAI,IAAI,cAQxD,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,qBAAqB,GAAI,cAAc,cAAc,EAAE,KAAG,cAAc,GAAG,SAoCvF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,UAAU,EAAE,aAAa,MAAM,KAAG,MA0C1E,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAOjD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,KAAG,MAanD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,WAAW,MAAM,GAAG,MAAM,KAAG,MAmB/D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAiB/C,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,eAAO,MAAM,eAAe,GAAI,UAAU,iBAAiB,KAAG,IAoG7D,CAAC"}
@@ -1,212 +0,0 @@
1
- // Copyright The Perses Authors
2
- // Licensed under the Apache License, Version 2.0 (the "License");
3
- // you may not use this file except in compliance with the License.
4
- // You may obtain a copy of the License at
5
- //
6
- // http://www.apache.org/licenses/LICENSE-2.0
7
- //
8
- // Unless required by applicable law or agreed to in writing, software
9
- // distributed under the License is distributed on an "AS IS" BASIS,
10
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- // See the License for the specific language governing permissions and
12
- // limitations under the License.
13
- export const isExportableData = (data)=>{
14
- return !!(data && typeof data === 'object' && 'series' in data && Array.isArray(data.series) && data.series.length > 0);
15
- };
16
- export const extractExportableData = (queryResults)=>{
17
- if (!queryResults || queryResults.length === 0) return undefined;
18
- const allSeries = [];
19
- let timeRange = undefined;
20
- let stepMs = undefined;
21
- let metadata = undefined;
22
- queryResults.forEach((query)=>{
23
- if (query?.data && typeof query.data === 'object' && 'series' in query.data) {
24
- const data = query.data;
25
- if (data.series && Array.isArray(data.series) && data.series.length > 0) {
26
- allSeries.push(...data.series);
27
- if (!timeRange && data.timeRange) {
28
- timeRange = data.timeRange;
29
- }
30
- if (!stepMs && data.stepMs) {
31
- stepMs = data.stepMs;
32
- }
33
- if (!metadata && data.metadata) {
34
- metadata = data.metadata;
35
- }
36
- }
37
- }
38
- });
39
- if (allSeries.length > 0) {
40
- return {
41
- series: allSeries,
42
- timeRange,
43
- stepMs,
44
- metadata
45
- };
46
- }
47
- return undefined;
48
- };
49
- export const formatLegendName = (series, seriesIndex)=>{
50
- const seriesAny = series;
51
- let legendName = series.formattedName || series.name;
52
- if (!legendName || legendName === `Series ${seriesIndex + 1}`) {
53
- legendName = seriesAny.legendName || seriesAny.displayName || seriesAny.legend || series.name || '';
54
- }
55
- if ((!legendName || legendName === series.name) && series.labels) {
56
- const labels = series.labels;
57
- const displayLabels = {
58
- ...labels
59
- };
60
- const metricName = displayLabels.__name__;
61
- delete displayLabels.__name__;
62
- const labelPairs = Object.entries(displayLabels).filter(([value])=>value !== undefined && value !== null && value !== '').map(([key, value])=>`${key}="${value}"`).join(', ');
63
- if (metricName && labelPairs) {
64
- legendName = `${metricName}{${labelPairs}}`;
65
- } else if (metricName) {
66
- legendName = metricName;
67
- } else if (labelPairs) {
68
- legendName = `{${labelPairs}}`;
69
- } else {
70
- legendName = labels.job || labels.instance || labels.metric || `Series ${seriesIndex + 1}`;
71
- }
72
- }
73
- if (!legendName || legendName.trim() === '') {
74
- legendName = `Series ${seriesIndex + 1}`;
75
- }
76
- return legendName;
77
- };
78
- export const sanitizeColumnName = (name)=>{
79
- return name.replace(/[,"\n\r]/g, '_').replace(/\s+/g, '_').replace(/_+/g, '_').replace(/^_|_$/g, '').substring(0, 255);
80
- };
81
- export const sanitizeFilename = (filename)=>{
82
- return filename.replace(/[<>:"/\\|?*]/g, ' ').trim().split(/\s+/).filter((word)=>word.length > 0).map((word, index)=>{
83
- if (index === 0) {
84
- return word.toLowerCase();
85
- }
86
- return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
87
- }).join('');
88
- };
89
- export const formatTimestampISO = (timestamp)=>{
90
- let timestampMs;
91
- if (typeof timestamp === 'string') {
92
- const date = new Date(timestamp);
93
- if (isNaN(date.getTime())) {
94
- return timestamp;
95
- }
96
- timestampMs = date.getTime();
97
- } else {
98
- timestampMs = timestamp > 1e10 ? timestamp : timestamp * 1000;
99
- }
100
- const date = new Date(timestampMs);
101
- if (isNaN(date.getTime())) {
102
- return new Date(timestampMs).toISOString();
103
- }
104
- return date.toISOString();
105
- };
106
- export const escapeCsvValue = (value)=>{
107
- if (value === null || value === undefined) {
108
- return '';
109
- }
110
- const stringValue = String(value);
111
- if (stringValue.includes(',') || stringValue.includes('"') || stringValue.includes('\n') || stringValue.includes('\r')) {
112
- return `"${stringValue.replace(/"/g, '""')}"`;
113
- }
114
- return stringValue;
115
- };
116
- export const exportDataAsCSV = ({ data })=>{
117
- if (!isExportableData(data)) {
118
- console.warn('No valid data found to export to CSV.');
119
- return new Blob([
120
- ''
121
- ], {
122
- type: 'text/csv;charset=utf-8'
123
- });
124
- }
125
- let csvString = '';
126
- const result = {};
127
- const seriesInfo = [];
128
- let validSeriesCount = 0;
129
- for(let i = 0; i < data.series.length; i++){
130
- const series = data.series[i];
131
- if (!series) {
132
- continue;
133
- }
134
- if (!Array.isArray(series.values) || series.values.length === 0) {
135
- continue;
136
- }
137
- const legendName = formatLegendName(series, i);
138
- const columnName = sanitizeColumnName(legendName);
139
- const currentSeriesInfo = {
140
- legendName,
141
- columnName: columnName || `Series_${i + 1}`,
142
- originalName: series.name || ''
143
- };
144
- seriesInfo.push(currentSeriesInfo);
145
- validSeriesCount++;
146
- for(let j = 0; j < series.values.length; j++){
147
- const entry = series.values[j];
148
- let timestamp;
149
- let value;
150
- if (Array.isArray(entry) && entry.length >= 2) {
151
- timestamp = entry[0];
152
- value = entry[1];
153
- } else if (typeof entry === 'object' && entry !== null && 'timestamp' in entry && 'value' in entry) {
154
- const dataPoint = entry;
155
- timestamp = dataPoint.timestamp;
156
- value = dataPoint.value;
157
- } else {
158
- continue;
159
- }
160
- if (value === null || value === undefined) {
161
- continue;
162
- }
163
- const dateTime = formatTimestampISO(timestamp);
164
- if (!result[dateTime]) {
165
- result[dateTime] = {};
166
- }
167
- result[dateTime][currentSeriesInfo.columnName] = value;
168
- }
169
- }
170
- if (validSeriesCount === 0 || seriesInfo.length === 0) {
171
- console.warn('No valid data found to export to CSV.');
172
- return new Blob([
173
- ''
174
- ], {
175
- type: 'text/csv;charset=utf-8'
176
- });
177
- }
178
- const timestampCount = Object.keys(result).length;
179
- if (timestampCount === 0) {
180
- console.warn('No valid timestamp data found to export to CSV.');
181
- return new Blob([
182
- ''
183
- ], {
184
- type: 'text/csv;charset=utf-8'
185
- });
186
- }
187
- const columnNames = seriesInfo.map((info)=>info.columnName);
188
- csvString += `DateTime,${columnNames.join(',')}\n`;
189
- const sortedDateTimes = Object.keys(result).sort((a, b)=>{
190
- const dateA = new Date(a).getTime();
191
- const dateB = new Date(b).getTime();
192
- return dateA - dateB;
193
- });
194
- for (const dateTime of sortedDateTimes){
195
- const rowData = result[dateTime];
196
- const values = [];
197
- if (rowData) {
198
- for (const columnName of columnNames){
199
- const value = rowData[columnName];
200
- values.push(escapeCsvValue(value));
201
- }
202
- csvString += `${escapeCsvValue(dateTime)},${values.join(',')}\n`;
203
- }
204
- }
205
- return new Blob([
206
- csvString
207
- ], {
208
- type: 'text/csv;charset=utf-8'
209
- });
210
- };
211
-
212
- //# sourceMappingURL=CSVExportUtils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/CSVExportUtils.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nexport interface SeriesDataPoint {\n timestamp: number | string;\n value: unknown;\n}\n\nexport interface DataSeries {\n name?: string;\n formattedName?: string;\n legendName?: string;\n displayName?: string;\n legend?: string;\n labels?: Record<string, string>;\n values: Array<[number | string, unknown]> | SeriesDataPoint[];\n}\n\nexport interface ExportableData {\n series: DataSeries[];\n timeRange?: {\n start: string | number;\n end: string | number;\n };\n stepMs?: number;\n metadata?: Record<string, unknown>;\n}\n\nexport const isExportableData = (data: unknown): data is ExportableData => {\n return !!(\n data &&\n typeof data === 'object' &&\n 'series' in data &&\n Array.isArray((data as ExportableData).series) &&\n (data as ExportableData).series.length > 0\n );\n};\n\nexport interface QueryDataInput {\n data?: unknown;\n error?: unknown;\n isFetching?: boolean;\n}\n\nexport const extractExportableData = (queryResults: QueryDataInput[]): ExportableData | undefined => {\n if (!queryResults || queryResults.length === 0) return undefined;\n\n const allSeries: DataSeries[] = [];\n let timeRange: ExportableData['timeRange'] = undefined;\n let stepMs: number | undefined = undefined;\n let metadata: ExportableData['metadata'] = undefined;\n\n queryResults.forEach((query) => {\n if (query?.data && typeof query.data === 'object' && 'series' in query.data) {\n const data = query.data as ExportableData;\n if (data.series && Array.isArray(data.series) && data.series.length > 0) {\n allSeries.push(...data.series);\n if (!timeRange && data.timeRange) {\n timeRange = data.timeRange;\n }\n if (!stepMs && data.stepMs) {\n stepMs = data.stepMs;\n }\n if (!metadata && data.metadata) {\n metadata = data.metadata;\n }\n }\n }\n });\n\n if (allSeries.length > 0) {\n return {\n series: allSeries,\n timeRange,\n stepMs,\n metadata,\n };\n }\n\n return undefined;\n};\n\nexport const formatLegendName = (series: DataSeries, seriesIndex: number): string => {\n const seriesAny = series as DataSeries & {\n formattedName?: string;\n legendName?: string;\n displayName?: string;\n legend?: string;\n labels?: Record<string, string>;\n };\n\n let legendName = series.formattedName || series.name;\n\n if (!legendName || legendName === `Series ${seriesIndex + 1}`) {\n legendName = seriesAny.legendName || seriesAny.displayName || seriesAny.legend || series.name || '';\n }\n\n if ((!legendName || legendName === series.name) && series.labels) {\n const labels = series.labels;\n const displayLabels = { ...labels };\n const metricName = displayLabels.__name__;\n delete displayLabels.__name__;\n\n const labelPairs = Object.entries(displayLabels)\n .filter(([value]) => value !== undefined && value !== null && value !== '')\n .map(([key, value]) => `${key}=\"${value}\"`)\n .join(', ');\n\n if (metricName && labelPairs) {\n legendName = `${metricName}{${labelPairs}}`;\n } else if (metricName) {\n legendName = metricName;\n } else if (labelPairs) {\n legendName = `{${labelPairs}}`;\n } else {\n legendName = labels.job || labels.instance || labels.metric || `Series ${seriesIndex + 1}`;\n }\n }\n\n if (!legendName || legendName.trim() === '') {\n legendName = `Series ${seriesIndex + 1}`;\n }\n\n return legendName;\n};\n\nexport const sanitizeColumnName = (name: string): string => {\n return name\n .replace(/[,\"\\n\\r]/g, '_')\n .replace(/\\s+/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '')\n .substring(0, 255);\n};\n\nexport const sanitizeFilename = (filename: string): string => {\n return filename\n .replace(/[<>:\"/\\\\|?*]/g, ' ')\n .trim()\n .split(/\\s+/)\n .filter((word) => word.length > 0)\n .map((word, index) => {\n if (index === 0) {\n return word.toLowerCase();\n }\n return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\n })\n .join('');\n};\n\nexport const formatTimestampISO = (timestamp: number | string): string => {\n let timestampMs: number;\n\n if (typeof timestamp === 'string') {\n const date = new Date(timestamp);\n if (isNaN(date.getTime())) {\n return timestamp;\n }\n timestampMs = date.getTime();\n } else {\n timestampMs = timestamp > 1e10 ? timestamp : timestamp * 1000;\n }\n\n const date = new Date(timestampMs);\n if (isNaN(date.getTime())) {\n return new Date(timestampMs).toISOString();\n }\n\n return date.toISOString();\n};\n\nexport const escapeCsvValue = (value: unknown): string => {\n if (value === null || value === undefined) {\n return '';\n }\n\n const stringValue = String(value);\n\n if (\n stringValue.includes(',') ||\n stringValue.includes('\"') ||\n stringValue.includes('\\n') ||\n stringValue.includes('\\r')\n ) {\n return `\"${stringValue.replace(/\"/g, '\"\"')}\"`;\n }\n\n return stringValue;\n};\n\nexport interface ExportDataOptions {\n data: ExportableData;\n}\n\nexport const exportDataAsCSV = ({ data }: ExportDataOptions): Blob => {\n if (!isExportableData(data)) {\n console.warn('No valid data found to export to CSV.');\n return new Blob([''], { type: 'text/csv;charset=utf-8' });\n }\n\n let csvString = '';\n const result: Record<string, Record<string, unknown>> = {};\n const seriesInfo: Array<{ legendName: string; columnName: string; originalName: string }> = [];\n let validSeriesCount = 0;\n\n for (let i = 0; i < data.series.length; i++) {\n const series = data.series[i];\n\n if (!series) {\n continue;\n }\n\n if (!Array.isArray(series.values) || series.values.length === 0) {\n continue;\n }\n\n const legendName = formatLegendName(series, i);\n const columnName = sanitizeColumnName(legendName);\n\n const currentSeriesInfo = {\n legendName,\n columnName: columnName || `Series_${i + 1}`,\n originalName: series.name || '',\n };\n\n seriesInfo.push(currentSeriesInfo);\n validSeriesCount++;\n\n for (let j = 0; j < series.values.length; j++) {\n const entry = series.values[j];\n\n let timestamp: number | string;\n let value: unknown;\n\n if (Array.isArray(entry) && entry.length >= 2) {\n timestamp = entry[0];\n value = entry[1];\n } else if (typeof entry === 'object' && entry !== null && 'timestamp' in entry && 'value' in entry) {\n const dataPoint = entry as SeriesDataPoint;\n timestamp = dataPoint.timestamp;\n value = dataPoint.value;\n } else {\n continue;\n }\n\n if (value === null || value === undefined) {\n continue;\n }\n\n const dateTime = formatTimestampISO(timestamp);\n\n if (!result[dateTime]) {\n result[dateTime] = {};\n }\n\n result[dateTime][currentSeriesInfo.columnName] = value;\n }\n }\n\n if (validSeriesCount === 0 || seriesInfo.length === 0) {\n console.warn('No valid data found to export to CSV.');\n return new Blob([''], { type: 'text/csv;charset=utf-8' });\n }\n\n const timestampCount = Object.keys(result).length;\n if (timestampCount === 0) {\n console.warn('No valid timestamp data found to export to CSV.');\n return new Blob([''], { type: 'text/csv;charset=utf-8' });\n }\n\n const columnNames = seriesInfo.map((info) => info.columnName);\n csvString += `DateTime,${columnNames.join(',')}\\n`;\n\n const sortedDateTimes = Object.keys(result).sort((a, b) => {\n const dateA = new Date(a).getTime();\n const dateB = new Date(b).getTime();\n return dateA - dateB;\n });\n\n for (const dateTime of sortedDateTimes) {\n const rowData = result[dateTime];\n const values: string[] = [];\n\n if (rowData) {\n for (const columnName of columnNames) {\n const value = rowData[columnName];\n values.push(escapeCsvValue(value));\n }\n\n csvString += `${escapeCsvValue(dateTime)},${values.join(',')}\\n`;\n }\n }\n\n return new Blob([csvString], { type: 'text/csv;charset=utf-8' });\n};\n"],"names":["isExportableData","data","Array","isArray","series","length","extractExportableData","queryResults","undefined","allSeries","timeRange","stepMs","metadata","forEach","query","push","formatLegendName","seriesIndex","seriesAny","legendName","formattedName","name","displayName","legend","labels","displayLabels","metricName","__name__","labelPairs","Object","entries","filter","value","map","key","join","job","instance","metric","trim","sanitizeColumnName","replace","substring","sanitizeFilename","filename","split","word","index","toLowerCase","charAt","toUpperCase","slice","formatTimestampISO","timestamp","timestampMs","date","Date","isNaN","getTime","toISOString","escapeCsvValue","stringValue","String","includes","exportDataAsCSV","console","warn","Blob","type","csvString","result","seriesInfo","validSeriesCount","i","values","columnName","currentSeriesInfo","originalName","j","entry","dataPoint","dateTime","timestampCount","keys","columnNames","info","sortedDateTimes","sort","a","b","dateA","dateB","rowData"],"mappings":"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"}
@@ -1,246 +0,0 @@
1
- // Copyright The Perses Authors
2
- // Licensed under the Apache License, Version 2.0 (the "License");
3
- // you may not use this file except in compliance with the License.
4
- // You may obtain a copy of the License at
5
- //
6
- // http://www.apache.org/licenses/LICENSE-2.0
7
- //
8
- // Unless required by applicable law or agreed to in writing, software
9
- // distributed under the License is distributed on an "AS IS" BASIS,
10
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- // See the License for the specific language governing permissions and
12
- // limitations under the License.
13
- "use strict";
14
- Object.defineProperty(exports, "__esModule", {
15
- value: true
16
- });
17
- function _export(target, all) {
18
- for(var name in all)Object.defineProperty(target, name, {
19
- enumerable: true,
20
- get: Object.getOwnPropertyDescriptor(all, name).get
21
- });
22
- }
23
- _export(exports, {
24
- get escapeCsvValue () {
25
- return escapeCsvValue;
26
- },
27
- get exportDataAsCSV () {
28
- return exportDataAsCSV;
29
- },
30
- get extractExportableData () {
31
- return extractExportableData;
32
- },
33
- get formatLegendName () {
34
- return formatLegendName;
35
- },
36
- get formatTimestampISO () {
37
- return formatTimestampISO;
38
- },
39
- get isExportableData () {
40
- return isExportableData;
41
- },
42
- get sanitizeColumnName () {
43
- return sanitizeColumnName;
44
- },
45
- get sanitizeFilename () {
46
- return sanitizeFilename;
47
- }
48
- });
49
- const isExportableData = (data)=>{
50
- return !!(data && typeof data === 'object' && 'series' in data && Array.isArray(data.series) && data.series.length > 0);
51
- };
52
- const extractExportableData = (queryResults)=>{
53
- if (!queryResults || queryResults.length === 0) return undefined;
54
- const allSeries = [];
55
- let timeRange = undefined;
56
- let stepMs = undefined;
57
- let metadata = undefined;
58
- queryResults.forEach((query)=>{
59
- if (query?.data && typeof query.data === 'object' && 'series' in query.data) {
60
- const data = query.data;
61
- if (data.series && Array.isArray(data.series) && data.series.length > 0) {
62
- allSeries.push(...data.series);
63
- if (!timeRange && data.timeRange) {
64
- timeRange = data.timeRange;
65
- }
66
- if (!stepMs && data.stepMs) {
67
- stepMs = data.stepMs;
68
- }
69
- if (!metadata && data.metadata) {
70
- metadata = data.metadata;
71
- }
72
- }
73
- }
74
- });
75
- if (allSeries.length > 0) {
76
- return {
77
- series: allSeries,
78
- timeRange,
79
- stepMs,
80
- metadata
81
- };
82
- }
83
- return undefined;
84
- };
85
- const formatLegendName = (series, seriesIndex)=>{
86
- const seriesAny = series;
87
- let legendName = series.formattedName || series.name;
88
- if (!legendName || legendName === `Series ${seriesIndex + 1}`) {
89
- legendName = seriesAny.legendName || seriesAny.displayName || seriesAny.legend || series.name || '';
90
- }
91
- if ((!legendName || legendName === series.name) && series.labels) {
92
- const labels = series.labels;
93
- const displayLabels = {
94
- ...labels
95
- };
96
- const metricName = displayLabels.__name__;
97
- delete displayLabels.__name__;
98
- const labelPairs = Object.entries(displayLabels).filter(([value])=>value !== undefined && value !== null && value !== '').map(([key, value])=>`${key}="${value}"`).join(', ');
99
- if (metricName && labelPairs) {
100
- legendName = `${metricName}{${labelPairs}}`;
101
- } else if (metricName) {
102
- legendName = metricName;
103
- } else if (labelPairs) {
104
- legendName = `{${labelPairs}}`;
105
- } else {
106
- legendName = labels.job || labels.instance || labels.metric || `Series ${seriesIndex + 1}`;
107
- }
108
- }
109
- if (!legendName || legendName.trim() === '') {
110
- legendName = `Series ${seriesIndex + 1}`;
111
- }
112
- return legendName;
113
- };
114
- const sanitizeColumnName = (name)=>{
115
- return name.replace(/[,"\n\r]/g, '_').replace(/\s+/g, '_').replace(/_+/g, '_').replace(/^_|_$/g, '').substring(0, 255);
116
- };
117
- const sanitizeFilename = (filename)=>{
118
- return filename.replace(/[<>:"/\\|?*]/g, ' ').trim().split(/\s+/).filter((word)=>word.length > 0).map((word, index)=>{
119
- if (index === 0) {
120
- return word.toLowerCase();
121
- }
122
- return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
123
- }).join('');
124
- };
125
- const formatTimestampISO = (timestamp)=>{
126
- let timestampMs;
127
- if (typeof timestamp === 'string') {
128
- const date = new Date(timestamp);
129
- if (isNaN(date.getTime())) {
130
- return timestamp;
131
- }
132
- timestampMs = date.getTime();
133
- } else {
134
- timestampMs = timestamp > 1e10 ? timestamp : timestamp * 1000;
135
- }
136
- const date = new Date(timestampMs);
137
- if (isNaN(date.getTime())) {
138
- return new Date(timestampMs).toISOString();
139
- }
140
- return date.toISOString();
141
- };
142
- const escapeCsvValue = (value)=>{
143
- if (value === null || value === undefined) {
144
- return '';
145
- }
146
- const stringValue = String(value);
147
- if (stringValue.includes(',') || stringValue.includes('"') || stringValue.includes('\n') || stringValue.includes('\r')) {
148
- return `"${stringValue.replace(/"/g, '""')}"`;
149
- }
150
- return stringValue;
151
- };
152
- const exportDataAsCSV = ({ data })=>{
153
- if (!isExportableData(data)) {
154
- console.warn('No valid data found to export to CSV.');
155
- return new Blob([
156
- ''
157
- ], {
158
- type: 'text/csv;charset=utf-8'
159
- });
160
- }
161
- let csvString = '';
162
- const result = {};
163
- const seriesInfo = [];
164
- let validSeriesCount = 0;
165
- for(let i = 0; i < data.series.length; i++){
166
- const series = data.series[i];
167
- if (!series) {
168
- continue;
169
- }
170
- if (!Array.isArray(series.values) || series.values.length === 0) {
171
- continue;
172
- }
173
- const legendName = formatLegendName(series, i);
174
- const columnName = sanitizeColumnName(legendName);
175
- const currentSeriesInfo = {
176
- legendName,
177
- columnName: columnName || `Series_${i + 1}`,
178
- originalName: series.name || ''
179
- };
180
- seriesInfo.push(currentSeriesInfo);
181
- validSeriesCount++;
182
- for(let j = 0; j < series.values.length; j++){
183
- const entry = series.values[j];
184
- let timestamp;
185
- let value;
186
- if (Array.isArray(entry) && entry.length >= 2) {
187
- timestamp = entry[0];
188
- value = entry[1];
189
- } else if (typeof entry === 'object' && entry !== null && 'timestamp' in entry && 'value' in entry) {
190
- const dataPoint = entry;
191
- timestamp = dataPoint.timestamp;
192
- value = dataPoint.value;
193
- } else {
194
- continue;
195
- }
196
- if (value === null || value === undefined) {
197
- continue;
198
- }
199
- const dateTime = formatTimestampISO(timestamp);
200
- if (!result[dateTime]) {
201
- result[dateTime] = {};
202
- }
203
- result[dateTime][currentSeriesInfo.columnName] = value;
204
- }
205
- }
206
- if (validSeriesCount === 0 || seriesInfo.length === 0) {
207
- console.warn('No valid data found to export to CSV.');
208
- return new Blob([
209
- ''
210
- ], {
211
- type: 'text/csv;charset=utf-8'
212
- });
213
- }
214
- const timestampCount = Object.keys(result).length;
215
- if (timestampCount === 0) {
216
- console.warn('No valid timestamp data found to export to CSV.');
217
- return new Blob([
218
- ''
219
- ], {
220
- type: 'text/csv;charset=utf-8'
221
- });
222
- }
223
- const columnNames = seriesInfo.map((info)=>info.columnName);
224
- csvString += `DateTime,${columnNames.join(',')}\n`;
225
- const sortedDateTimes = Object.keys(result).sort((a, b)=>{
226
- const dateA = new Date(a).getTime();
227
- const dateB = new Date(b).getTime();
228
- return dateA - dateB;
229
- });
230
- for (const dateTime of sortedDateTimes){
231
- const rowData = result[dateTime];
232
- const values = [];
233
- if (rowData) {
234
- for (const columnName of columnNames){
235
- const value = rowData[columnName];
236
- values.push(escapeCsvValue(value));
237
- }
238
- csvString += `${escapeCsvValue(dateTime)},${values.join(',')}\n`;
239
- }
240
- }
241
- return new Blob([
242
- csvString
243
- ], {
244
- type: 'text/csv;charset=utf-8'
245
- });
246
- };