From: Alexander Moisseev Date: Wed, 26 Nov 2025 14:39:14 +0000 (+0300) Subject: [Fix] Update D3 libs: bug fixes & validation X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6d4d678b557af4c782ca523232bfc4c5f76e5cd1;p=thirdparty%2Frspamd.git [Fix] Update D3 libs: bug fixes & validation - D3Evolution 2.0.3 → 2.0.4: * Fix hover highlight regression after D3 v7 migration * Fix memory leaks in destroy() method * Optimize hover performance (replace DOM traversal) * Fix legend circle flickering on interaction * Fix potential negative index in cursor positioning - rspamd-D3Pie 1.1.1 → 1.1.2: * Fix crash when rapidly updating with different datasets * Fix data array corruption during quick dataset changes * Add comprehensive options validation with constraints * Add ID format validation and duplicate label detection * Improve error handling and descriptive messages * Add donut mask support for inner radius > 0 * Fix memory leaks with event handler cleanup * Improve transition interruption detection --- diff --git a/interface/js/lib/d3evolution.min.js b/interface/js/lib/d3evolution.min.js index ceedf77578..f975988e03 100644 --- a/interface/js/lib/d3evolution.min.js +++ b/interface/js/lib/d3evolution.min.js @@ -1,5 +1,5 @@ /*! - * D3Evolution 2.0.3 (https://github.com/moisseev/D3Evolution) + * D3Evolution 2.0.4 (https://github.com/moisseev/D3Evolution) * Copyright (c) 2016-2017, Alexander Moisseev, BSD 2-Clause */ -function D3Evolution(t,e){var l=$.extend(!0,{title:"",width:800,height:400,margin:{top:80,right:60,bottom:40,left:60},yAxisLabel:"",type:"line",yScale:"lin",duration:1250,interpolate:"curveLinear",legend:{buttonRadius:7,space:130,entries:[]}},e);this.destroy=function(){d3.selectAll("#"+t+" svg").remove()},this.destroy();let n={curveLinear:d3.curveLinear,curveStep:d3.curveStep,curveStepBefore:d3.curveStepBefore,curveStepAfter:d3.curveStepAfter,curveMonotoneX:d3.curveMonotoneX,curveBasis:d3.curveBasis,curveBasisOpen:d3.curveBasisOpen,curveBundle:d3.curveBundle,curveCardinal:d3.curveCardinal,curveCardinalOpen:d3.curveCardinalOpen,curveCatmullRom:d3.curveCatmullRom,curveCatmullRomOpen:d3.curveCatmullRomOpen,curveNatural:d3.curveNatural};var o=null,i=null,c=null,u=l.width-l.margin.left-l.margin.right,r=l.height-l.margin.top-l.margin.bottom,s=d3.scaleTime().range([0,u]),d=null,a=null;function p(){a="log"===l.yScale?(d=d3.scaleLog().clamp(!0).range([r,0]),d3.scaleLog().range([r-30,0])):(d=d3.scaleLinear().range([r,0])).copy()}p();function y(t){return void 0!==l.legend.entries[t]&&void 0!==l.legend.entries[t].color?l.legend.entries[t].color:H(t)}function f(t){return void 0!==l.legend.entries[t]&&void 0!==l.legend.entries[t].label?l.legend.entries[t].label:"path_"+t}var g=d3.axisBottom().scale(s),h=d3.axisLeft().scale(a).ticks(5),m=d3.axisBottom().tickFormat("").scale(s).tickSize(-r,0),v=d3.axisLeft().tickFormat("").scale(a).tickSize(-u,0),D=d3.scaleQuantize().range([r,0]),T=d3.area().x(function(t){return s(t.x)}).y0(function(){return r}).y1(function(t){return D(null===t.y)}).curve(d3.curveStep),x=d3.line().defined(function(t){return null!==t.y}).x(function(t){return s(t.x)}).y(function(t){return d(t.y)}).curve(n[l.interpolate]),A=d3.area().defined(function(t){return null!==t.y}).x(function(t){return s(t.x)}).y0(function(t){return d(t.y0)}).y1(function(t){return d(t.y0+t.y)}).curve(n[l.interpolate]),X=function(t){t.reduce(function(n,t){return t.forEach(function(t,e){t.y0=n.length?n[e].y+n[e].y0:0}),t},[])},H=d3.scaleOrdinal(d3.schemeCategory10),Q=function(t){var n=t.reduce(function(n,t){return t.map(function(t,e){return t.y+(n[e]||0)})},[]),t=$.extend(!0,[],t);return t.forEach(function(t){t.forEach(function(t,e){n[e]&&(t.y/=n[e])})}),t};function k(){if("log"===l.yScale){let e=d.invert(r);o.forEach(function(t){t.forEach(function(t){return 0===t.y?t.y:e})})}}let b=d3.select("#"+t).append("svg").classed("d3evolution",!0).attr("width",l.width).attr("height",l.height);var S=b.append("g").attr("class","legend"),L=b.append("g").attr("width",u).attr("height",r).attr("transform","translate("+l.margin.left+", "+l.margin.top+")"),e=(L.append("g").attr("class","x grid").attr("transform","translate(0,"+r+")").call(m),L.append("g").attr("class","y grid").attr("transform","translate(0,0)").call(v),L.append("g").attr("class","x axis").attr("transform","translate(0,"+r+")").call(g),L.append("g").attr("class","y axis").attr("transform","translate(0,0)").call(h),d3.scaleOrdinal().domain([0]).range([r])),w=d3.axisLeft().scale(e),R=(L.append("g").attr("class","y-zero axis").call(w),L.append("text").attr("class","y label").attr("x",20-l.margin.left).attr("y",-20).style("opacity","percentage"===l.convert?0:1).text(l.yAxisLabel)),B=b.append("svg:text").attr("x",l.width/2).attr("y",l.margin.top/3).attr("text-anchor","middle"),e=(B.append("tspan").attr("class","chart-title").text(l.title+" "),B.timeRange=B.append("tspan"),b.append("svg:text").attr("x",l.width-20).attr("y",l.margin.top/3).attr("text-anchor","end")),V=e.append("tspan").attr("class","cursor-time");e.append("svg:title").text("Current cursor position");let C=function(t){return d3.timeFormat("%Y-%m-%d %H:%M:%S")(new Date(t))};function M(e){var n=o.map(function(t){return t[e]}),t=n[0].x;return V.text(C(t)),S.selectAll("text.value").text(function(t,e){return null===n[e].y?null:d3.format("percentage"===l.convert?".2~%":".6~")(n[e].y)}),n}var O=null,E=null;function Y(t){var n,e=d3.bisector(function(t){return t.x}).left,t=s.invert(d3.pointer(t)[0]);o&&o[0]&&o[0].length&&(n=M(e(o[0],t)-1),O.selectAll(".x,.cursor circle").attr("transform","translate("+s(n[0].x)+",0)"),O.selectAll(".y").attr("transform",function(t,e){e=n[e];return"translate(0,"+(("area"===l.type?d(e.y0+e.y):d(e.y))||0)+")"}).style("display",function(t,e){return n[e].y?null:"none"}))}function j(){O.style("display","none"),M(E)}function q(){O.style("display",null)}L.append("rect").style("fill","none").style("pointer-events","all").attr("width",u).attr("height",r).on("mousemove",Y).on("mouseout",j).on("mouseover",q);function G(){o="percentage"===l.convert?(R.transition().duration(l.duration).style("opacity",0),Q(i)):(R.transition().duration(l.duration).style("opacity",1),i),E=i[0].length-1,z()}var F=L.append("g"),_=L.append("g"),z=((O=L.append("g").attr("class","cursor").style("pointer-events","none").style("display","none")).append("line").attr("class","x background").attr("y1",0).attr("y2",r),O.append("line").attr("class","x foreground").attr("y1",0).attr("y2",r),function(){var t=[];if(t="area"===l.type?(X(o),"log"===l.yScale?d3.extent(d3.merge(o),function(t){return t.y0+t.y===0?null:t.y0+t.y}):d3.extent(d3.merge(o),function(t){return t.y0+t.y})):"log"===l.yScale?d3.extent(d3.merge(o),function(t){return 0===t.y?null:t.y}):d3.extent(d3.merge(o),function(t){return t.y}),"log"===l.yScale?(void 0===t[0]?t=[.0095,.0105]:t[0]===t[1]&&(t[0]*=.9),a.domain([t[0],t[1]]),e=a.invert(r),d.domain([e,t[1]])):(d.domain([0{e.on("click",t=>{t=e.nodes().indexOf(t.currentTarget);N[t]=0===N[t]?1:0,d3.select("#circle_"+t).transition().duration(l.duration).style("fill-opacity",N[t]+.2),d3.select("#path_"+t).transition().duration(l.duration).style("opacity",N[t])})};i=$.extend(!0,[],t),c=l.width-l.margin.right-l.legend.space*i.length,i.forEach(function(t){t.forEach(function(t){t.x*=1e3})});var t=d3.extent(d3.merge(i),function(t){return t.x}),t=(s.domain([t[0],t[1]]),B.timeRange.text("[ "+C(t[0])+" / "+C(t[1])+" ]"),F.selectAll("path.path-null").data(i)),t=(t.enter().append("path").attr("class","path-null"),F.selectAll("path.path-null").transition().duration(l.duration/2).style("opacity",0).on("end",function(){F.selectAll("path.path-null").attr("d",T).transition().duration(l.duration/2).style("opacity",1)}),t.exit().remove(),G(),k(),_.selectAll("path.path").data(o)),t=(e(t.enter().append("path").merge(t).attr("class","path").attr("id",function(t,e){return"path_"+e}).on("mousemove",Y).on("mouseover",function(t,e,n){r(n),q()}).on("mouseout",function(t,e,n){r(n,!1),j()})),t.exit().remove(),t=_.selectAll("path.path"),"area"===l.type?t.style("fill",function(t,e){return y(e)}).style("stroke","none").style("fill-opacity",function(t,e){return N[e]}):t.style("fill","none").style("stroke",function(t,e){return y(e)}).style("opacity",function(t,e){return N[e]}),t.transition().duration(l.duration).attr("d","area"===l.type?A:x),d3.transition().duration(l.duration)),t=(L.select(".x.grid").transition(t).call(m.scale(s)),L.select(".x.axis").transition(t).call(g.scale(s)),O.selectAll(".y").data(o)),n=t.enter().append("g").attr("class","y").style("stroke",function(t,e){return y(e)}),n=(n.append("circle").attr("class","background"),n.append("circle").attr("class","foreground"),n.selectAll("circle").attr("r",7).style("fill","none"),n.append("line").attr("class","background"),n.append("line").attr("class","foreground"),n.selectAll("line").attr("x1",0).attr("x2",u),t.exit().remove(),S.selectAll("circle").data(o)),t=(e(n.enter().append("circle").attr("id",function(t,e){return"circle_"+e}).attr("cy",2*l.margin.top/3).attr("r",l.legend.buttonRadius).style("fill",function(t,e){return y(e)}).style("stroke",function(t,e){return y(e)}).style("fill-opacity",function(t,e){return N[e]+.2}).on("mouseover",function(t,e,n){r(n)}).on("mouseout",function(t,e,n){r(n,!1)})),n.exit().remove(),S.selectAll("circle").transition().duration(l.duration).attr("cx",function(t,e){return c+l.legend.space*e}),S.selectAll("g").data(o)),n=t.enter().append("g"),a=(e(n.append("text").attr("class","name").attr("dy","0.3em").text(function(t,e){return f(e)}).on("mouseover",function(t,e,n){r(n)}).on("mouseout",function(t,e,n){r(n,!1)})),n.append("text").attr("class","value").attr("dy","20"),t.exit().remove(),I(),S.selectAll("text.value"));return a.transition("opacity").duration(l.duration/2).style("opacity",0).on("end",function(){M(E),a.transition("opacity").duration(l.duration/2).style("opacity",1)}),this},this.legend=function(t){return $.extend(!0,l.legend,t),S.selectAll("circle").transition().duration(l.duration).attr("cx",function(t,e){return c+l.legend.space*e}).attr("r",l.legend.buttonRadius).style("fill",function(t,e){return y(e)}).style("stroke",function(t,e){return y(e)}),S.selectAll("text.name").text(function(t,e){return f(e)}),I(),_.selectAll("path.path").transition().duration(l.duration).style("fill","area"===l.type?function(t,e){return y(e)}:"none").style("stroke","area"!==l.type?function(t,e){return y(e)}:"none"),O.selectAll(".y").style("stroke",function(t,e){return y(e)}),this},this.convert=function(t){return l.convert=t,G(),M(E),_.selectAll("path.path").data(o).transition().duration(l.duration).attr("d","area"===l.type?A:x),this},this.interpolate=function(t){return l.interpolate=t,A.curve(n[l.interpolate]),x.curve(n[l.interpolate]),_.selectAll("path.path").attr("d","area"===l.type?A:x),this},this.type=function(t){return l.type=t,z(),_.selectAll("path.path").style("stroke","area"!==l.type?function(t,e){return y(e)}:"none").style("fill","area"===l.type?function(t,e){return y(e)}:"none").transition().duration(l.duration).attr("d","area"===l.type?A:x),this},this.yAxisLabel=function(t){return l.yAxisLabel=t,R.transition().duration(l.duration/2).style("opacity",0).on("end",function(){R.text(l.yAxisLabel).transition().duration(l.duration/2).style("opacity",1)}),this},this.yScale=function(t){return l.yScale=t,p(),k(),z(),_.selectAll("path.path").transition().duration(l.duration).attr("d","area"===l.type?A:x),this}} \ No newline at end of file +function D3Evolution(t,e){"use strict";var n=$.extend(!0,{title:"",width:800,height:400,margin:{top:80,right:60,bottom:40,left:60},yAxisLabel:"",type:"line",yScale:"lin",duration:1250,interpolate:"curveLinear",legend:{buttonRadius:7,space:130,entries:[]}},e);this.destroy=function(){d3.select("#"+t).selectAll("*").on("click",null).on("mousemove",null).on("mouseover",null).on("mouseout",null),d3.selectAll("#"+t+" svg").remove()},this.destroy();const r={curveLinear:d3.curveLinear,curveStep:d3.curveStep,curveStepBefore:d3.curveStepBefore,curveStepAfter:d3.curveStepAfter,curveMonotoneX:d3.curveMonotoneX,curveBasis:d3.curveBasis,curveBasisOpen:d3.curveBasisOpen,curveBundle:d3.curveBundle,curveCardinal:d3.curveCardinal,curveCardinalOpen:d3.curveCardinalOpen,curveCatmullRom:d3.curveCatmullRom,curveCatmullRomOpen:d3.curveCatmullRomOpen,curveNatural:d3.curveNatural};var a=null,l=null,i=null,o=n.width-n.margin.left-n.margin.right,c=n.height-n.margin.top-n.margin.bottom,u=d3.scaleTime().range([0,o]),s=null,d=null;const p=function(){"log"===n.yScale?(s=d3.scaleLog().clamp(!0).range([c,0]),d=d3.scaleLog().range([c-30,0])):(s=d3.scaleLinear().range([c,0]),d=s.copy())};p();var y=d3.axisBottom().scale(u),f=d3.axisLeft().scale(d).ticks(5),g=d3.axisBottom().tickFormat("").scale(u).tickSize(-c,0),v=d3.axisLeft().tickFormat("").scale(d).tickSize(-o,0),h=d3.scaleQuantize().range([c,0]),m=d3.area().x(function(t){return u(t.x)}).y0(function(){return c}).y1(function(t){return h(null===t.y)}).curve(d3.curveStep),x=d3.line().defined(function(t){return null!==t.y}).x(function(t){return u(t.x)}).y(function(t){return s(t.y)}).curve(r[n.interpolate]),A=d3.area().defined(function(t){return null!==t.y}).x(function(t){return u(t.x)}).y0(function(t){return s(t.y0)}).y1(function(t){return s(t.y0+t.y)}).curve(r[n.interpolate]),k=d3.scaleOrdinal(d3.schemeCategory10),b=function(t){return void 0!==n.legend.entries[t]&&void 0!==n.legend.entries[t].color?n.legend.entries[t].color:k(t)},S=function(t){return void 0!==n.legend.entries[t]&&void 0!==n.legend.entries[t].label?n.legend.entries[t].label:"path_"+t};const L=function(){if("log"===n.yScale){const t=s.invert(c);a.forEach(function(e){e.forEach(function(e){return 0===e.y?e.y:t})})}};var O=d3.select("#"+t).append("svg").classed("d3evolution",!0).attr("width",n.width).attr("height",n.height),w=O.append("g").attr("class","legend"),R=O.append("g").attr("width",o).attr("height",c).attr("transform","translate("+n.margin.left+", "+n.margin.top+")");R.append("g").attr("class","x grid").attr("transform","translate(0,"+c+")").call(g),R.append("g").attr("class","y grid").attr("transform","translate(0,0)").call(v),R.append("g").attr("class","x axis").attr("transform","translate(0,"+c+")").call(y),R.append("g").attr("class","y axis").attr("transform","translate(0,0)").call(f);var B=d3.scaleOrdinal().domain([0]).range([c]),C=d3.axisLeft().scale(B);R.append("g").attr("class","y-zero axis").call(C);var M=R.append("text").attr("class","y label").attr("x",20-n.margin.left).attr("y",-20).style("opacity","percentage"===n.convert?0:1).text(n.yAxisLabel),E=O.append("svg:text").attr("x",n.width/2).attr("y",n.margin.top/3).attr("text-anchor","middle");E.append("tspan").attr("class","chart-title").text(n.title+" "),E.timeRange=E.append("tspan");var F=O.append("svg:text").attr("x",n.width-20).attr("y",n.margin.top/3).attr("text-anchor","end"),_=F.append("tspan").attr("class","cursor-time");F.append("svg:title").text("Current cursor position");const z=function(t){return d3.timeFormat("%Y-%m-%d %H:%M:%S")(new Date(t))};function N(t){var e=a.map(function(e){return e[t]}),r=e[0].x;return _.text(z(r)),w.selectAll("text.value").text(function(t,r){return null===e[r].y?null:d3.format("percentage"===n.convert?".2~%":".6~")(e[r].y)}),e}var D=null,X=null;function H(t){var e=d3.bisector(function(t){return t.x}).left,r=u.invert(d3.pointer(t)[0]);if(a&&a[0]&&a[0].length){var l=N(Math.max(0,e(a[0],r)-1));D.selectAll(".x,.cursor circle").attr("transform","translate("+u(l[0].x)+",0)"),D.selectAll(".y").attr("transform",function(t,e){var r=l[e];return"translate(0,"+(("area"===n.type?s(r.y0+r.y):s(r.y))||0)+")"}).style("display",function(t,e){return l[e].y?null:"none"})}}function Q(){D.style("display","none"),N(X)}function T(){D.style("display",null)}R.append("rect").style("fill","none").style("pointer-events","all").attr("width",o).attr("height",c).on("mousemove",H).on("mouseout",Q).on("mouseover",T);var V=R.append("g"),Y=R.append("g");(D=R.append("g").attr("class","cursor").style("pointer-events","none").style("display","none")).append("line").attr("class","x background").attr("y1",0).attr("y2",c),D.append("line").attr("class","x foreground").attr("y1",0).attr("y2",c);var j=function(){var t="area"===n.type?(a.reduce(function(t,e){return e.forEach(function(e,n){e.y0=t.length?t[n].y+t[n].y0:0}),e},[]),"log"===n.yScale?d3.extent(d3.merge(a),function(t){return t.y0+t.y===0?null:t.y0+t.y}):d3.extent(d3.merge(a),function(t){return t.y0+t.y})):"log"===n.yScale?d3.extent(d3.merge(a),function(t){return 0===t.y?null:t.y}):d3.extent(d3.merge(a),function(t){return t.y});if("log"===n.yScale){void 0===t[0]?t=[.0095,.0105]:t[0]===t[1]&&(t[0]*=.9),d.domain([t[0],t[1]]);var e=d.invert(c);s.domain([e,t[1]])}else s.domain([t[0]>0?0:t[0],t[1]]),d.domain(s.domain());if("percentage"===n.convert){var r={y:c};const t=d3.format(".0%");C.tickFormat(t),f.tickFormat("log"===n.yScale?function(e){return function(t,e,n){const r=Math.pow(10,Math.round(Math.log(t)/Math.LN10));return Math.abs(r-t)<1e-6||!(Math.abs(s(r)-s(t))<15||e.y-s(t)<15)?(e.y=s(t),n(t)):""}(e,r,t)}:t)}else C.tickFormat(null),f.tickFormat(null);f.tickValues(d.ticks().length?null:[t[0],t[1]]);const l=d3.transition().duration(n.duration);R.select(".y.grid").transition(l).call(v.scale(d)),R.select(".y.axis").transition(l).call(f.scale(d)),R.select(".y-zero.axis").call(C)},q=function(){var t,e,r;"percentage"===n.convert?(M.transition().duration(n.duration).style("opacity",0),e=(t=l).reduce(function(t,e){return e.map(function(e,n){return e.y+(t[n]?t[n]:0)})},[]),(r=$.extend(!0,[],t)).forEach(function(t){t.forEach(function(t,n){e[n]&&(t.y/=e[n])})}),a=r):(M.transition().duration(n.duration).style("opacity",1),a=l),X=l[0].length-1,j()};function G(t){return"translate("+(i+n.legend.space*t+2*n.legend.buttonRadius)+","+2*n.margin.top/3+")"}function I(t){(t||w.selectAll("g")).transition().duration(n.duration).attr("transform",function(t,e){return G(e)})}var J=[];this.data=function(t){var e=t=>{t.on("click",(t,e)=>{const r=a.indexOf(e);J[r]=0===J[r]?1:0,d3.select("#circle_"+r).transition().duration(n.duration).style("fill-opacity",0===J[r]?.2:1),d3.select("#path_"+r).transition().duration(n.duration).style("opacity",J[r])})};const r=function(t,e){d3.select("#circle_"+t).attr("r",n.legend.buttonRadius*(!1===e?1:1.3));const r=function(n){return!1===e?J[n]:n===t?1:0===J[n]?0:.4};Y.selectAll("path.path").style("opacity",function(t,e){return r(e)}).style("fill-opacity",function(t,e){return r(e)})};for(l=$.extend(!0,[],t),i=n.width-n.margin.right-n.legend.space*l.length;J.length{r(a.indexOf(e)),T()}).on("mouseout",(t,e)=>{r(a.indexOf(e),!1),Q()})),d.exit().remove(),d=Y.selectAll("path.path"),"area"===n.type?d.style("fill",function(t,e){return b(e)}).style("stroke","none").style("fill-opacity",function(t,e){return J[e]}):d.style("fill","none").style("stroke",function(t,e){return b(e)}).style("opacity",function(t,e){return J[e]}),d.transition().duration(n.duration).attr("d","area"===n.type?A:x);const p=d3.transition().duration(n.duration);R.select(".x.grid").transition(p).call(g.scale(u)),R.select(".x.axis").transition(p).call(y.scale(u));var f=D.selectAll(".y").data(a),v=f.enter().append("g").attr("class","y").style("stroke",function(t,e){return b(e)});v.append("circle").attr("class","background"),v.append("circle").attr("class","foreground"),v.selectAll("circle").attr("r",7).style("fill","none"),v.append("line").attr("class","background"),v.append("line").attr("class","foreground"),v.selectAll("line").attr("x1",0).attr("x2",o),f.exit().remove();var h=w.selectAll("circle").data(a);e(h.enter().append("circle").attr("id",function(t,e){return"circle_"+e}).attr("cy",2*n.margin.top/3).attr("r",n.legend.buttonRadius).attr("cx",function(t,e){return i+n.legend.space*e}).style("fill",function(t,e){return b(e)}).style("stroke",function(t,e){return b(e)}).style("fill-opacity",function(t,e){return 0===J[e]?.2:1}).on("mouseover",(t,e)=>r(a.indexOf(e))).on("mouseout",(t,e)=>r(a.indexOf(e),!1))),h.exit().remove(),h.transition().duration(n.duration).attr("cx",function(t,e){return i+n.legend.space*e}).style("fill-opacity",function(t,e){return 0===J[e]?.2:1});var k=w.selectAll("g").data(a),O=k.enter().append("g").attr("transform",function(t,e){return G(e)});e(O.append("text").attr("class","name").attr("dy","0.3em").text(function(t,e){return S(e)}).on("mouseover",(t,e)=>r(a.indexOf(e))).on("mouseout",(t,e)=>r(a.indexOf(e),!1))),O.append("text").attr("class","value").attr("dy","20"),k.exit().remove(),I(k);var B=w.selectAll("text.value");return B.transition("opacity").duration(n.duration/2).style("opacity",0).on("end",function(){N(X),B.transition("opacity").duration(n.duration/2).style("opacity",1)}),this},this.legend=function(t){return $.extend(!0,n.legend,t),w.selectAll("circle").transition().duration(n.duration).attr("cx",function(t,e){return i+n.legend.space*e}).attr("r",n.legend.buttonRadius).style("fill",function(t,e){return b(e)}).style("stroke",function(t,e){return b(e)}),w.selectAll("text.name").text(function(t,e){return S(e)}),I(),Y.selectAll("path.path").transition().duration(n.duration).style("fill","area"===n.type?function(t,e){return b(e)}:"none").style("stroke","area"!==n.type?function(t,e){return b(e)}:"none"),D.selectAll(".y").style("stroke",function(t,e){return b(e)}),this},this.convert=function(t){return n.convert=t,q(),N(X),Y.selectAll("path.path").data(a).transition().duration(n.duration).attr("d","area"===n.type?A:x),this},this.interpolate=function(t){return n.interpolate=t,A.curve(r[n.interpolate]),x.curve(r[n.interpolate]),Y.selectAll("path.path").attr("d","area"===n.type?A:x),this},this.type=function(t){return n.type=t,j(),Y.selectAll("path.path").style("stroke","area"!==n.type?function(t,e){return b(e)}:"none").style("fill","area"===n.type?function(t,e){return b(e)}:"none").transition().duration(n.duration).attr("d","area"===n.type?A:x),this},this.yAxisLabel=function(t){return n.yAxisLabel=t,M.transition().duration(n.duration/2).style("opacity",0).on("end",function(){M.text(n.yAxisLabel).transition().duration(n.duration/2).style("opacity",1)}),this},this.yScale=function(t){return n.yScale=t,p(),L(),j(),Y.selectAll("path.path").transition().duration(n.duration).attr("d","area"===n.type?A:x),this}} \ No newline at end of file diff --git a/interface/js/lib/d3pie.min.js b/interface/js/lib/d3pie.min.js index 968d33444b..c59fb11522 100644 --- a/interface/js/lib/d3pie.min.js +++ b/interface/js/lib/d3pie.min.js @@ -1,5 +1,5 @@ /*! - * rspamd-D3Pie 1.1.1 (https://github.com/moisseev/rspamd-D3Pie) + * rspamd-D3Pie 1.1.2 (https://github.com/moisseev/rspamd-D3Pie) * Copyright (c) 2022, Alexander Moisseev, BSD 2-Clause */ -function D3Pie(g,t){let h=$.extend(!0,{canvasPadding:5,cornerRadius:3,duration:1250,gradient:{enabled:!0,percentage:100},labels:{inner:{hideWhenLessThanPercentage:4,offset:.15},outer:{collideHeight:13,format:"label",pieDistance:30}},padAngle:.01,pieCenterOffset:{x:0,y:0},size:{canvasHeight:400,canvasWidth:600,pieInnerRadius:"20%",pieOuterRadius:"85%"},title:"",total:{enabled:!1}},t);this.destroy=function(){d3.selectAll("#"+g+" svg, #"+g+"-tooltip").remove()},this.destroy();var e,t=d3.select("#"+g).append("svg").attr("class","d3pie").attr("width",h.size.canvasWidth).attr("height",h.size.canvasHeight);let l=0,b=(""!==h.title&&((e=t.append("svg:text").attr("class","chart-title").attr("x",h.size.canvasWidth/2)).append("tspan").text(h.title+" "),l=e.node().getBBox().height,e.attr("y",l+h.canvasPadding)),t.append("g").attr("transform","translate("+(h.size.canvasWidth/2+h.pieCenterOffset.x)+","+(h.size.canvasHeight/2+l/2+h.pieCenterOffset.y)+")")),v={},A={},{outerRadius:x,innerRadius:y}=(()=>{function t(t,e){var a;return/%/u.test(t)?(a=Math.max(0,Math.min(99,parseInt(t.replace(/[\D]/u,""),10)))/100,Math.floor(e*a)):parseInt(t,10)}var e=h.size.canvasWidth-2*h.canvasPadding,a=h.size.canvasHeight-2*h.canvasPadding-l;let n=Math.min(e,a)/2;return"none"!==h.labels.outer.format&&(e=parseInt(h.labels.outer.pieDistance,10),n>e)&&(n-=e),{outerRadius:a=t(h.size.pieOuterRadius,n),innerRadius:t(h.size.pieInnerRadius,a)}})(),m=x+h.labels.outer.pieDistance,M=d3.line().curve(d3.curveCatmullRomOpen),R=d3.select("body").append("div").attr("id",g+"-tooltip").attr("class","d3pie-tooltip"),r=R.append("span").attr("id",g+"-tooltip-text");function w(t){t.on("mouseover",function(t,e){var a=R.datum().total,n=a?Math.round(100*e.data.value/a):NaN;e.data.value?(R.transition().duration(300).style("opacity",1),r.text(e.data.label+(a?": "+e.data.value+" ("+n+"%)":""))):R.transition().duration(300).style("opacity",0),R.each(function(t){t.height=this.getBoundingClientRect().height})}).on("mouseout",function(){R.transition().duration(300).style("opacity",0)}).on("mousemove",t=>{let{pageX:e,pageY:a}=t;R.style("left",e+"px").style("top",function(t){return a-t.height-2+"px"})})}let z=b.append("g"),P=(w(z),z.append("circle").attr("r",y).style("opacity",0),h.total.enabled&&((e=z.append("text").attr("class","total-text")).append("tspan").attr("class","total-value").style("font-size",.6*y+"px"),e.append("tspan").attr("x","0").attr("dy",.5*y).text(void 0!==h.total.label?h.total.label:"Total")),t.append("defs"));this.data=function(t){let l=$.extend(!0,[],t),s=[],e=l.reduce(function(t,e){return t+(e.value||0)},0),a=(R.datum({total:e}),z.datum({data:{label:void 0!==h.total.label?h.total.label:"Total",value:e}}),h.total.enabled&&z.select(".total-value").text(d3.format(".3~s")(e)),l.unshift({label:"undefined",color:h.gradient.enabled?"steelblue":"#ecf1f5",value:0===e?1:0}),d3.scaleOrdinal(d3.schemeSet1));function n(t,e){return void 0!==t&&void 0!==t.color?t.color:a(e)}function o(t,e,a=e){return d3.arc().innerRadius(e).outerRadius(a).centroid(t)}function c(t){return d3.interpolate(v[t.data.label],t)}function u(t){var e=m-.1;return Math.max(-e,Math.min(e,t))}function r(r,i){A[r.data.label].newAngle=(()=>{var t=u(s[i].y);let e=Math.sqrt(Math.pow(m,2)-Math.pow(t,2)),a=((r.endAngle+r.startAngle)/2>Math.PI&&(e*=-1),Math.PI/2-Math.atan2(-t,e));return a<0&&(a+=2*Math.PI),{startAngle:a,endAngle:a}})();let d=d3.interpolate(A[r.data.label].currentAngle,A[r.data.label].newAngle);return function(t){var e=o(d(t),m),[a,n]=e,l=0= "+e.min+", got: "+r):void 0!==e.max&&r>e.max&&a.push(t+" must be <= "+e.max+", got: "+r):a.push(t+" must be a finite number, got: "+n)}function i(t){const e=l(t);if("number"==typeof e)(!isFinite(e)||e<0)&&a.push(t+" must be a non-negative number, got: "+e);else if("string"==typeof e){const n=/^(?\d+)%$/u.exec(e);if(n){const e=parseInt(n.groups.pct,10);e>99&&a.push(t+" percentage must be 0-99, got: "+e+"%")}else a.push(t+' must be a number or percentage string (e.g. "85%"), got: '+e)}else a.push(t+" must be a number or percentage string, got: "+typeof e)}if(r("canvasPadding",{min:0}),r("cornerRadius",{min:0}),r("duration",{min:0}),r("gradient.percentage",{min:0,max:100}),r("labels.inner.hideWhenLessThanPercentage",{min:0,max:100}),r("labels.inner.offset",{min:-1,max:1}),r("labels.outer.collideHeight",{min:1}),r("labels.outer.pieDistance",{min:0}),r("padAngle",{min:0,max:2*Math.PI}),r("pieCenterOffset.x",{}),r("pieCenterOffset.y",{}),r("size.canvasHeight",{min:50}),r("size.canvasWidth",{min:50}),i("size.pieOuterRadius"),i("size.pieInnerRadius"),function(t,e){const n=l(t);if(!e.includes(n)){const l=e.map(t=>'"'+t+'"').join(", ");a.push(t+" must be one of ["+l+'], got: "'+n+'"')}}("labels.outer.format",["none","label"]),a.length>0)throw new Error("D3Pie configuration errors:\n - "+a.join("\n - "));this.destroy=function(){d3.select("#"+t).selectAll("*").on("click",null).on("mousemove",null).on("mouseover",null).on("mouseout",null),d3.selectAll("#"+t+" svg, #"+t+"-tooltip").remove()},this.destroy();const s=d3.select("#"+t).append("svg").attr("class","d3pie").attr("width",n.size.canvasWidth).attr("height",n.size.canvasHeight);let o=0;if(""!==n.title){const t=s.append("svg:text").attr("class","chart-title").attr("x",n.size.canvasWidth/2);t.append("tspan").text(n.title+" "),o=t.node().getBBox().height,t.attr("y",o+n.canvasPadding)}const c=s.append("g").attr("transform","translate("+(n.size.canvasWidth/2+n.pieCenterOffset.x)+","+(n.size.canvasHeight/2+o/2+n.pieCenterOffset.y)+")"),d={},u={},{outerRadius:p,innerRadius:f}=function(){function t(t,e){if(!/%/u.test(t))return parseInt(t,10);const n=Math.max(0,Math.min(99,parseInt(t.replace(/[\D]/u,""),10)))/100;return Math.floor(e*n)}const e=n.size.canvasWidth-2*n.canvasPadding,a=n.size.canvasHeight-2*n.canvasPadding-o;let l=Math.min(e,a)/2;if("none"!==n.labels.outer.format){const t=parseInt(n.labels.outer.pieDistance,10);l>t&&(l-=t)}const r=t(n.size.pieOuterRadius,l);return{outerRadius:r,innerRadius:t(n.size.pieInnerRadius,r)}}(),g=p+n.labels.outer.pieDistance,h=d3.line().curve(d3.curveCatmullRomOpen),b=d3.select("body").append("div").attr("id",t+"-tooltip").attr("class","d3pie-tooltip"),m=b.append("span").attr("id",t+"-tooltip-text");function v(t){t.on("mouseover",function(t,e){const n=b.datum().total,a=n?Math.round(100*e.data.value/n):NaN;e.data.value?(b.transition().duration(300).style("opacity",1),m.text(e.data.label+(n?": "+e.data.value+" ("+a+"%)":""))):b.transition().duration(300).style("opacity",0),b.each(function(t){t.height=this.getBoundingClientRect().height})}).on("mouseout",function(){b.transition().duration(300).style("opacity",0)}).on("mousemove",t=>{const{pageX:e,pageY:n}=t;b.style("left",e+"px").style("top",function(t){return n-t.height-2+"px"})})}const x=c.append("g"),y=c.append("g");if(v(y),y.append("circle").attr("r",f).style("opacity",0),n.total.enabled){const t=y.append("text").attr("class","total-text");t.append("tspan").attr("class","total-value").style("font-size",.6*f+"px"),t.append("tspan").attr("x","0").attr("dy",.5*f).text(void 0!==n.total.label?n.total.label:"Total")}const A=s.append("defs");if(f>0){const e=A.append("mask").attr("id",t+"-donut-mask");e.append("rect").attr("x",-n.size.canvasWidth).attr("y",-n.size.canvasHeight).attr("width",2*n.size.canvasWidth).attr("height",2*n.size.canvasHeight).attr("fill","white"),e.append("circle").attr("r",f).attr("fill","black"),x.attr("mask","url(#"+t+"-donut-mask)")}this.data=function(e){let a=$.extend(!0,[],e);const l=new Set;for(let t=0;t{t&&"object"==typeof t&&"startAngle"in t&&"endAngle"in t||console.error("D3Pie error:",t)}),D.append("text").attr("class","inner-label").attr("dy",".35em"),x.selectAll(".inner-label").data(R(a),P).text(function(t){return"undefined"===t.data.label?"undefined":Math.round(100*t.data.value/i)+"%"}).transition(z).attrTween("opacity",function(t){return t.data.value?function(e){const a=m(t)(e);return 100*(a.endAngle-a.startAngle)/(2*Math.PI)=0?n.labels.outer.collideHeight:-n.labels.outer.collideHeight),r.push({fx:l,y:s})}),d3.forceSimulation(r).alphaMin(.5).force("collide",d3.forceCollide(n.labels.outer.collideHeight/2)).force("boundY",function(){for(const t of r)t.y=w(t.y)}).tick(30);const t=D.append("g").attr("class","outer-label-g");t.append("text").attr("class","outer-label").attr("dy",".35em").text(P),t.append("path").attr("class","link"),x.selectAll(".outer-label-g").data(R(a),P).transition(z).style("opacity",function(t,e){return e&&t.value?1:0}).each(function(t,e){$(this).children(".link").attr("stroke",o(t.data,e))}),x.selectAll(".outer-label").data(R(a),P).transition(z).attrTween("transform",function(t,e){u[t.data.label].newAngle=function(){const n=w(r[e].y);let a=Math.sqrt(Math.pow(g,2)-Math.pow(n,2));(t.endAngle+t.startAngle)/2>Math.PI&&(a*=-1);let l=Math.PI/2-Math.atan2(-n,a);return l<0&&(l+=2*Math.PI),{startAngle:l,endAngle:l}}();const n=d3.interpolate(u[t.data.label].currentAngle,u[t.data.label].newAngle);return function(a){const l=c(n(a),g),[r,i]=l,s=r>0?{dx:5,textAnchor:"start"}:{dx:-5,textAnchor:"end"};return d3.select(x.selectAll(".link").nodes()[e]).datum([c(m(t)(a),p),c(m(t)(a),p+5),[r,i],[r+s.dx,i]]).attr("d",h),d3.select(x.selectAll(".outer-label").nodes()[e]).attr("dx",s.dx).style("text-anchor",s.textAnchor),"translate("+l+")"}})}}} \ No newline at end of file