Cookie Notice by dFactory - Version 2.4.0

Version Description

  • New: Advanced Multisite support
  • Fix: Polylang translation not working for shortcode
  • Fix: Parse error: syntax error, unexpected [
Download this release

Release Info

Developer dfactory
Plugin Icon 128x128 Cookie Notice by dFactory
Version 2.4.0
Comparing to
See all releases

Code changes from version 2.3.1 to 2.4.0

assets/chartjs/chart.min.js CHANGED
@@ -1,13 +1,13 @@
1
  /*!
2
- * Chart.js v3.7.0
3
  * https://www.chartjs.org
4
- * (c) 2021 Chart.js Contributors
5
  * Released under the MIT License
6
  */
7
  !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";const t="undefined"==typeof window?function(t){return t()}:window.requestAnimationFrame;function e(e,i,s){const n=s||(t=>Array.prototype.slice.call(t));let o=!1,a=[];return function(...s){a=n(s),o||(o=!0,t.call(window,(()=>{o=!1,e.apply(i,a)})))}}function i(t,e){let i;return function(...s){return e?(clearTimeout(i),i=setTimeout(t,e,s)):t.apply(this,s),e}}const s=t=>"start"===t?"left":"end"===t?"right":"center",n=(t,e,i)=>"start"===t?e:"end"===t?i:(e+i)/2,o=(t,e,i,s)=>t===(s?"left":"right")?i:"center"===t?(e+i)/2:e;var a=new class{constructor(){this._request=null,this._charts=new Map,this._running=!1,this._lastDate=void 0}_notify(t,e,i,s){const n=e.listeners[s],o=e.duration;n.forEach((s=>s({chart:t,initial:e.initial,numSteps:o,currentStep:Math.min(i-e.start,o)})))}_refresh(){this._request||(this._running=!0,this._request=t.call(window,(()=>{this._update(),this._request=null,this._running&&this._refresh()})))}_update(t=Date.now()){let e=0;this._charts.forEach(((i,s)=>{if(!i.running||!i.items.length)return;const n=i.items;let o,a=n.length-1,r=!1;for(;a>=0;--a)o=n[a],o._active?(o._total>i.duration&&(i.duration=o._total),o.tick(t),r=!0):(n[a]=n[n.length-1],n.pop());r&&(s.draw(),this._notify(s,i,t,"progress")),n.length||(i.running=!1,this._notify(s,i,t,"complete"),i.initial=!1),e+=n.length})),this._lastDate=t,0===e&&(this._running=!1)}_getAnims(t){const e=this._charts;let i=e.get(t);return i||(i={running:!1,initial:!0,items:[],listeners:{complete:[],progress:[]}},e.set(t,i)),i}listen(t,e,i){this._getAnims(t).listeners[e].push(i)}add(t,e){e&&e.length&&this._getAnims(t).items.push(...e)}has(t){return this._getAnims(t).items.length>0}start(t){const e=this._charts.get(t);e&&(e.running=!0,e.start=Date.now(),e.duration=e.items.reduce(((t,e)=>Math.max(t,e._duration)),0),this._refresh())}running(t){if(!this._running)return!1;const e=this._charts.get(t);return!!(e&&e.running&&e.items.length)}stop(t){const e=this._charts.get(t);if(!e||!e.items.length)return;const i=e.items;let s=i.length-1;for(;s>=0;--s)i[s].cancel();e.items=[],this._notify(t,e,Date.now(),"complete")}remove(t){return this._charts.delete(t)}};
8
  /*!
9
- * @kurkle/color v0.1.9
10
  * https://github.com/kurkle/color#readme
11
- * (c) 2020 Jukka Kurkela
12
  * Released under the MIT License
13
- */const r={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},l="0123456789ABCDEF",h=t=>l[15&t],c=t=>l[(240&t)>>4]+l[15&t],d=t=>(240&t)>>4==(15&t);function u(t){var e=function(t){return d(t.r)&&d(t.g)&&d(t.b)&&d(t.a)}(t)?h:c;return t?"#"+e(t.r)+e(t.g)+e(t.b)+(t.a<255?e(t.a):""):t}function f(t){return t+.5|0}const g=(t,e,i)=>Math.max(Math.min(t,i),e);function p(t){return g(f(2.55*t),0,255)}function m(t){return g(f(255*t),0,255)}function x(t){return g(f(t/2.55)/100,0,1)}function b(t){return g(f(100*t),0,100)}const _=/^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;const y=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function v(t,e,i){const s=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-s*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function w(t,e,i){const s=(s,n=(s+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[s(5),s(3),s(1)]}function M(t,e,i){const s=v(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)s[n]*=1-e-i,s[n]+=e;return s}function k(t){const e=t.r/255,i=t.g/255,s=t.b/255,n=Math.max(e,i,s),o=Math.min(e,i,s),a=(n+o)/2;let r,l,h;return n!==o&&(h=n-o,l=a>.5?h/(2-n-o):h/(n+o),r=n===e?(i-s)/h+(i<s?6:0):n===i?(s-e)/h+2:(e-i)/h+4,r=60*r+.5),[0|r,l||0,a]}function S(t,e,i,s){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,s)).map(m)}function P(t,e,i){return S(v,t,e,i)}function D(t){return(t%360+360)%360}function C(t){const e=y.exec(t);let i,s=255;if(!e)return;e[5]!==i&&(s=e[6]?p(+e[5]):m(+e[5]));const n=D(+e[2]),o=+e[3]/100,a=+e[4]/100;return i="hwb"===e[1]?function(t,e,i){return S(M,t,e,i)}(n,o,a):"hsv"===e[1]?function(t,e,i){return S(w,t,e,i)}(n,o,a):P(n,o,a),{r:i[0],g:i[1],b:i[2],a:s}}const O={x:"dark",Z:"light",Y:"re",X:"blu",W:"gr",V:"medium",U:"slate",A:"ee",T:"ol",S:"or",B:"ra",C:"lateg",D:"ights",R:"in",Q:"turquois",E:"hi",P:"ro",O:"al",N:"le",M:"de",L:"yello",F:"en",K:"ch",G:"arks",H:"ea",I:"ightg",J:"wh"},A={OiceXe:"f0f8ff",antiquewEte:"faebd7",aqua:"ffff",aquamarRe:"7fffd4",azuY:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"0",blanKedOmond:"ffebcd",Xe:"ff",XeviTet:"8a2be2",bPwn:"a52a2a",burlywood:"deb887",caMtXe:"5f9ea0",KartYuse:"7fff00",KocTate:"d2691e",cSO:"ff7f50",cSnflowerXe:"6495ed",cSnsilk:"fff8dc",crimson:"dc143c",cyan:"ffff",xXe:"8b",xcyan:"8b8b",xgTMnPd:"b8860b",xWay:"a9a9a9",xgYF:"6400",xgYy:"a9a9a9",xkhaki:"bdb76b",xmagFta:"8b008b",xTivegYF:"556b2f",xSange:"ff8c00",xScEd:"9932cc",xYd:"8b0000",xsOmon:"e9967a",xsHgYF:"8fbc8f",xUXe:"483d8b",xUWay:"2f4f4f",xUgYy:"2f4f4f",xQe:"ced1",xviTet:"9400d3",dAppRk:"ff1493",dApskyXe:"bfff",dimWay:"696969",dimgYy:"696969",dodgerXe:"1e90ff",fiYbrick:"b22222",flSOwEte:"fffaf0",foYstWAn:"228b22",fuKsia:"ff00ff",gaRsbSo:"dcdcdc",ghostwEte:"f8f8ff",gTd:"ffd700",gTMnPd:"daa520",Way:"808080",gYF:"8000",gYFLw:"adff2f",gYy:"808080",honeyMw:"f0fff0",hotpRk:"ff69b4",RdianYd:"cd5c5c",Rdigo:"4b0082",ivSy:"fffff0",khaki:"f0e68c",lavFMr:"e6e6fa",lavFMrXsh:"fff0f5",lawngYF:"7cfc00",NmoncEffon:"fffacd",ZXe:"add8e6",ZcSO:"f08080",Zcyan:"e0ffff",ZgTMnPdLw:"fafad2",ZWay:"d3d3d3",ZgYF:"90ee90",ZgYy:"d3d3d3",ZpRk:"ffb6c1",ZsOmon:"ffa07a",ZsHgYF:"20b2aa",ZskyXe:"87cefa",ZUWay:"778899",ZUgYy:"778899",ZstAlXe:"b0c4de",ZLw:"ffffe0",lime:"ff00",limegYF:"32cd32",lRF:"faf0e6",magFta:"ff00ff",maPon:"800000",VaquamarRe:"66cdaa",VXe:"cd",VScEd:"ba55d3",VpurpN:"9370db",VsHgYF:"3cb371",VUXe:"7b68ee",VsprRggYF:"fa9a",VQe:"48d1cc",VviTetYd:"c71585",midnightXe:"191970",mRtcYam:"f5fffa",mistyPse:"ffe4e1",moccasR:"ffe4b5",navajowEte:"ffdead",navy:"80",Tdlace:"fdf5e6",Tive:"808000",TivedBb:"6b8e23",Sange:"ffa500",SangeYd:"ff4500",ScEd:"da70d6",pOegTMnPd:"eee8aa",pOegYF:"98fb98",pOeQe:"afeeee",pOeviTetYd:"db7093",papayawEp:"ffefd5",pHKpuff:"ffdab9",peru:"cd853f",pRk:"ffc0cb",plum:"dda0dd",powMrXe:"b0e0e6",purpN:"800080",YbeccapurpN:"663399",Yd:"ff0000",Psybrown:"bc8f8f",PyOXe:"4169e1",saddNbPwn:"8b4513",sOmon:"fa8072",sandybPwn:"f4a460",sHgYF:"2e8b57",sHshell:"fff5ee",siFna:"a0522d",silver:"c0c0c0",skyXe:"87ceeb",UXe:"6a5acd",UWay:"708090",UgYy:"708090",snow:"fffafa",sprRggYF:"ff7f",stAlXe:"4682b4",tan:"d2b48c",teO:"8080",tEstN:"d8bfd8",tomato:"ff6347",Qe:"40e0d0",viTet:"ee82ee",JHt:"f5deb3",wEte:"ffffff",wEtesmoke:"f5f5f5",Lw:"ffff00",LwgYF:"9acd32"};let T;function L(t){T||(T=function(){const t={},e=Object.keys(A),i=Object.keys(O);let s,n,o,a,r;for(s=0;s<e.length;s++){for(a=r=e[s],n=0;n<i.length;n++)o=i[n],r=r.replace(o,O[o]);o=parseInt(A[a],16),t[r]=[o>>16&255,o>>8&255,255&o]}return t}(),T.transparent=[0,0,0,0]);const e=T[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}function R(t,e,i){if(t){let s=k(t);s[e]=Math.max(0,Math.min(s[e]+s[e]*i,0===e?360:1)),s=P(s),t.r=s[0],t.g=s[1],t.b=s[2]}}function E(t,e){return t?Object.assign(e||{},t):t}function I(t){var e={r:0,g:0,b:0,a:255};return Array.isArray(t)?t.length>=3&&(e={r:t[0],g:t[1],b:t[2],a:255},t.length>3&&(e.a=m(t[3]))):(e=E(t,{r:0,g:0,b:0,a:1})).a=m(e.a),e}function z(t){return"r"===t.charAt(0)?function(t){const e=_.exec(t);let i,s,n,o=255;if(e){if(e[7]!==i){const t=+e[7];o=255&(e[8]?p(t):255*t)}return i=+e[1],s=+e[3],n=+e[5],i=255&(e[2]?p(i):i),s=255&(e[4]?p(s):s),n=255&(e[6]?p(n):n),{r:i,g:s,b:n,a:o}}}(t):C(t)}class F{constructor(t){if(t instanceof F)return t;const e=typeof t;let i;var s,n,o;"object"===e?i=I(t):"string"===e&&(o=(s=t).length,"#"===s[0]&&(4===o||5===o?n={r:255&17*r[s[1]],g:255&17*r[s[2]],b:255&17*r[s[3]],a:5===o?17*r[s[4]]:255}:7!==o&&9!==o||(n={r:r[s[1]]<<4|r[s[2]],g:r[s[3]]<<4|r[s[4]],b:r[s[5]]<<4|r[s[6]],a:9===o?r[s[7]]<<4|r[s[8]]:255})),i=n||L(t)||z(t)),this._rgb=i,this._valid=!!i}get valid(){return this._valid}get rgb(){var t=E(this._rgb);return t&&(t.a=x(t.a)),t}set rgb(t){this._rgb=I(t)}rgbString(){return this._valid?(t=this._rgb)&&(t.a<255?`rgba(${t.r}, ${t.g}, ${t.b}, ${x(t.a)})`:`rgb(${t.r}, ${t.g}, ${t.b})`):this._rgb;var t}hexString(){return this._valid?u(this._rgb):this._rgb}hslString(){return this._valid?function(t){if(!t)return;const e=k(t),i=e[0],s=b(e[1]),n=b(e[2]);return t.a<255?`hsla(${i}, ${s}%, ${n}%, ${x(t.a)})`:`hsl(${i}, ${s}%, ${n}%)`}(this._rgb):this._rgb}mix(t,e){const i=this;if(t){const s=i.rgb,n=t.rgb;let o;const a=e===o?.5:e,r=2*a-1,l=s.a-n.a,h=((r*l==-1?r:(r+l)/(1+r*l))+1)/2;o=1-h,s.r=255&h*s.r+o*n.r+.5,s.g=255&h*s.g+o*n.g+.5,s.b=255&h*s.b+o*n.b+.5,s.a=a*s.a+(1-a)*n.a,i.rgb=s}return i}clone(){return new F(this.rgb)}alpha(t){return this._rgb.a=m(t),this}clearer(t){return this._rgb.a*=1-t,this}greyscale(){const t=this._rgb,e=f(.3*t.r+.59*t.g+.11*t.b);return t.r=t.g=t.b=e,this}opaquer(t){return this._rgb.a*=1+t,this}negate(){const t=this._rgb;return t.r=255-t.r,t.g=255-t.g,t.b=255-t.b,this}lighten(t){return R(this._rgb,2,t),this}darken(t){return R(this._rgb,2,-t),this}saturate(t){return R(this._rgb,1,t),this}desaturate(t){return R(this._rgb,1,-t),this}rotate(t){return function(t,e){var i=k(t);i[0]=D(i[0]+e),i=P(i),t.r=i[0],t.g=i[1],t.b=i[2]}(this._rgb,t),this}}function B(t){return new F(t)}const V=t=>t instanceof CanvasGradient||t instanceof CanvasPattern;function W(t){return V(t)?t:B(t)}function N(t){return V(t)?t:B(t).saturate(.5).darken(.1).hexString()}function H(){}const j=function(){let t=0;return function(){return t++}}();function $(t){return null==t}function Y(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.substr(0,7)&&"Array]"===e.substr(-6)}function U(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}const X=t=>("number"==typeof t||t instanceof Number)&&isFinite(+t);function q(t,e){return X(t)?t:e}function K(t,e){return void 0===t?e:t}const G=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:t/e,Z=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function J(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function Q(t,e,i,s){let n,o,a;if(Y(t))if(o=t.length,s)for(n=o-1;n>=0;n--)e.call(i,t[n],n);else for(n=0;n<o;n++)e.call(i,t[n],n);else if(U(t))for(a=Object.keys(t),o=a.length,n=0;n<o;n++)e.call(i,t[a[n]],a[n])}function tt(t,e){let i,s,n,o;if(!t||!e||t.length!==e.length)return!1;for(i=0,s=t.length;i<s;++i)if(n=t[i],o=e[i],n.datasetIndex!==o.datasetIndex||n.index!==o.index)return!1;return!0}function et(t){if(Y(t))return t.map(et);if(U(t)){const e=Object.create(null),i=Object.keys(t),s=i.length;let n=0;for(;n<s;++n)e[i[n]]=et(t[i[n]]);return e}return t}function it(t){return-1===["__proto__","prototype","constructor"].indexOf(t)}function st(t,e,i,s){if(!it(t))return;const n=e[t],o=i[t];U(n)&&U(o)?nt(n,o,s):e[t]=et(o)}function nt(t,e,i){const s=Y(e)?e:[e],n=s.length;if(!U(t))return t;const o=(i=i||{}).merger||st;for(let a=0;a<n;++a){if(!U(e=s[a]))continue;const n=Object.keys(e);for(let s=0,a=n.length;s<a;++s)o(n[s],t,e,i)}return t}function ot(t,e){return nt(t,e,{merger:at})}function at(t,e,i){if(!it(t))return;const s=e[t],n=i[t];U(s)&&U(n)?ot(s,n):Object.prototype.hasOwnProperty.call(e,t)||(e[t]=et(n))}function rt(t,e){const i=t.indexOf(".",e);return-1===i?t.length:i}function lt(t,e){if(""===e)return t;let i=0,s=rt(e,i);for(;t&&s>i;)t=t[e.substr(i,s-i)],i=s+1,s=rt(e,i);return t}function ht(t){return t.charAt(0).toUpperCase()+t.slice(1)}const ct=t=>void 0!==t,dt=t=>"function"==typeof t,ut=(t,e)=>{if(t.size!==e.size)return!1;for(const i of t)if(!e.has(i))return!1;return!0};function ft(t){return"mouseup"===t.type||"click"===t.type||"contextmenu"===t.type}const gt=Object.create(null),pt=Object.create(null);function mt(t,e){if(!e)return t;const i=e.split(".");for(let e=0,s=i.length;e<s;++e){const s=i[e];t=t[s]||(t[s]=Object.create(null))}return t}function xt(t,e,i){return"string"==typeof e?nt(mt(t,e),i):nt(mt(t,""),e)}var bt=new class{constructor(t){this.animation=void 0,this.backgroundColor="rgba(0,0,0,0.1)",this.borderColor="rgba(0,0,0,0.1)",this.color="#666",this.datasets={},this.devicePixelRatio=t=>t.chart.platform.getDevicePixelRatio(),this.elements={},this.events=["mousemove","mouseout","click","touchstart","touchmove"],this.font={family:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",size:12,style:"normal",lineHeight:1.2,weight:null},this.hover={},this.hoverBackgroundColor=(t,e)=>N(e.backgroundColor),this.hoverBorderColor=(t,e)=>N(e.borderColor),this.hoverColor=(t,e)=>N(e.color),this.indexAxis="x",this.interaction={mode:"nearest",intersect:!0},this.maintainAspectRatio=!0,this.onHover=null,this.onClick=null,this.parsing=!0,this.plugins={},this.responsive=!0,this.scale=void 0,this.scales={},this.showLine=!0,this.drawActiveElementsOnTop=!0,this.describe(t)}set(t,e){return xt(this,t,e)}get(t){return mt(this,t)}describe(t,e){return xt(pt,t,e)}override(t,e){return xt(gt,t,e)}route(t,e,i,s){const n=mt(this,t),o=mt(this,i),a="_"+e;Object.defineProperties(n,{[a]:{value:n[e],writable:!0},[e]:{enumerable:!0,get(){const t=this[a],e=o[s];return U(t)?Object.assign({},e,t):K(t,e)},set(t){this[a]=t}}})}}({_scriptable:t=>!t.startsWith("on"),_indexable:t=>"events"!==t,hover:{_fallback:"interaction"},interaction:{_scriptable:!1,_indexable:!1}});const _t=Math.PI,yt=2*_t,vt=yt+_t,wt=Number.POSITIVE_INFINITY,Mt=_t/180,kt=_t/2,St=_t/4,Pt=2*_t/3,Dt=Math.log10,Ct=Math.sign;function Ot(t){const e=Math.round(t);t=Lt(t,e,t/1e3)?e:t;const i=Math.pow(10,Math.floor(Dt(t))),s=t/i;return(s<=1?1:s<=2?2:s<=5?5:10)*i}function At(t){const e=[],i=Math.sqrt(t);let s;for(s=1;s<i;s++)t%s==0&&(e.push(s),e.push(t/s));return i===(0|i)&&e.push(i),e.sort(((t,e)=>t-e)).pop(),e}function Tt(t){return!isNaN(parseFloat(t))&&isFinite(t)}function Lt(t,e,i){return Math.abs(t-e)<i}function Rt(t,e){const i=Math.round(t);return i-e<=t&&i+e>=t}function Et(t,e,i){let s,n,o;for(s=0,n=t.length;s<n;s++)o=t[s][i],isNaN(o)||(e.min=Math.min(e.min,o),e.max=Math.max(e.max,o))}function It(t){return t*(_t/180)}function zt(t){return t*(180/_t)}function Ft(t){if(!X(t))return;let e=1,i=0;for(;Math.round(t*e)/e!==t;)e*=10,i++;return i}function Bt(t,e){const i=e.x-t.x,s=e.y-t.y,n=Math.sqrt(i*i+s*s);let o=Math.atan2(s,i);return o<-.5*_t&&(o+=yt),{angle:o,distance:n}}function Vt(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function Wt(t,e){return(t-e+vt)%yt-_t}function Nt(t){return(t%yt+yt)%yt}function Ht(t,e,i,s){const n=Nt(t),o=Nt(e),a=Nt(i),r=Nt(o-n),l=Nt(a-n),h=Nt(n-o),c=Nt(n-a);return n===o||n===a||s&&o===a||r>l&&h<c}function jt(t,e,i){return Math.max(e,Math.min(i,t))}function $t(t){return jt(t,-32768,32767)}function Yt(t,e,i,s=1e-6){return t>=Math.min(e,i)-s&&t<=Math.max(e,i)+s}function Ut(t){return!t||$(t.size)||$(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family}function Xt(t,e,i,s,n){let o=e[n];return o||(o=e[n]=t.measureText(n).width,i.push(n)),o>s&&(s=o),s}function qt(t,e,i,s){let n=(s=s||{}).data=s.data||{},o=s.garbageCollect=s.garbageCollect||[];s.font!==e&&(n=s.data={},o=s.garbageCollect=[],s.font=e),t.save(),t.font=e;let a=0;const r=i.length;let l,h,c,d,u;for(l=0;l<r;l++)if(d=i[l],null!=d&&!0!==Y(d))a=Xt(t,n,o,a,d);else if(Y(d))for(h=0,c=d.length;h<c;h++)u=d[h],null==u||Y(u)||(a=Xt(t,n,o,a,u));t.restore();const f=o.length/2;if(f>i.length){for(l=0;l<f;l++)delete n[o[l]];o.splice(0,f)}return a}function Kt(t,e,i){const s=t.currentDevicePixelRatio,n=0!==i?Math.max(i/2,.5):0;return Math.round((e-n)*s)/s+n}function Gt(t,e){(e=e||t.getContext("2d")).save(),e.resetTransform(),e.clearRect(0,0,t.width,t.height),e.restore()}function Zt(t,e,i,s){let n,o,a,r,l;const h=e.pointStyle,c=e.rotation,d=e.radius;let u=(c||0)*Mt;if(h&&"object"==typeof h&&(n=h.toString(),"[object HTMLImageElement]"===n||"[object HTMLCanvasElement]"===n))return t.save(),t.translate(i,s),t.rotate(u),t.drawImage(h,-h.width/2,-h.height/2,h.width,h.height),void t.restore();if(!(isNaN(d)||d<=0)){switch(t.beginPath(),h){default:t.arc(i,s,d,0,yt),t.closePath();break;case"triangle":t.moveTo(i+Math.sin(u)*d,s-Math.cos(u)*d),u+=Pt,t.lineTo(i+Math.sin(u)*d,s-Math.cos(u)*d),u+=Pt,t.lineTo(i+Math.sin(u)*d,s-Math.cos(u)*d),t.closePath();break;case"rectRounded":l=.516*d,r=d-l,o=Math.cos(u+St)*r,a=Math.sin(u+St)*r,t.arc(i-o,s-a,l,u-_t,u-kt),t.arc(i+a,s-o,l,u-kt,u),t.arc(i+o,s+a,l,u,u+kt),t.arc(i-a,s+o,l,u+kt,u+_t),t.closePath();break;case"rect":if(!c){r=Math.SQRT1_2*d,t.rect(i-r,s-r,2*r,2*r);break}u+=St;case"rectRot":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+a,s-o),t.lineTo(i+o,s+a),t.lineTo(i-a,s+o),t.closePath();break;case"crossRot":u+=St;case"cross":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o);break;case"star":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o),u+=St,o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o);break;case"line":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a);break;case"dash":t.moveTo(i,s),t.lineTo(i+Math.cos(u)*d,s+Math.sin(u)*d)}t.fill(),e.borderWidth>0&&t.stroke()}}function Jt(t,e,i){return i=i||.5,!e||t&&t.x>e.left-i&&t.x<e.right+i&&t.y>e.top-i&&t.y<e.bottom+i}function Qt(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()}function te(t){t.restore()}function ee(t,e,i,s,n){if(!e)return t.lineTo(i.x,i.y);if("middle"===n){const s=(e.x+i.x)/2;t.lineTo(s,e.y),t.lineTo(s,i.y)}else"after"===n!=!!s?t.lineTo(e.x,i.y):t.lineTo(i.x,e.y);t.lineTo(i.x,i.y)}function ie(t,e,i,s){if(!e)return t.lineTo(i.x,i.y);t.bezierCurveTo(s?e.cp1x:e.cp2x,s?e.cp1y:e.cp2y,s?i.cp2x:i.cp1x,s?i.cp2y:i.cp1y,i.x,i.y)}function se(t,e,i,s,n,o={}){const a=Y(e)?e:[e],r=o.strokeWidth>0&&""!==o.strokeColor;let l,h;for(t.save(),t.font=n.string,function(t,e){e.translation&&t.translate(e.translation[0],e.translation[1]);$(e.rotation)||t.rotate(e.rotation);e.color&&(t.fillStyle=e.color);e.textAlign&&(t.textAlign=e.textAlign);e.textBaseline&&(t.textBaseline=e.textBaseline)}(t,o),l=0;l<a.length;++l)h=a[l],r&&(o.strokeColor&&(t.strokeStyle=o.strokeColor),$(o.strokeWidth)||(t.lineWidth=o.strokeWidth),t.strokeText(h,i,s,o.maxWidth)),t.fillText(h,i,s,o.maxWidth),ne(t,i,s,h,o),s+=n.lineHeight;t.restore()}function ne(t,e,i,s,n){if(n.strikethrough||n.underline){const o=t.measureText(s),a=e-o.actualBoundingBoxLeft,r=e+o.actualBoundingBoxRight,l=i-o.actualBoundingBoxAscent,h=i+o.actualBoundingBoxDescent,c=n.strikethrough?(l+h)/2:h;t.strokeStyle=t.fillStyle,t.beginPath(),t.lineWidth=n.decorationWidth||2,t.moveTo(a,c),t.lineTo(r,c),t.stroke()}}function oe(t,e){const{x:i,y:s,w:n,h:o,radius:a}=e;t.arc(i+a.topLeft,s+a.topLeft,a.topLeft,-kt,_t,!0),t.lineTo(i,s+o-a.bottomLeft),t.arc(i+a.bottomLeft,s+o-a.bottomLeft,a.bottomLeft,_t,kt,!0),t.lineTo(i+n-a.bottomRight,s+o),t.arc(i+n-a.bottomRight,s+o-a.bottomRight,a.bottomRight,kt,0,!0),t.lineTo(i+n,s+a.topRight),t.arc(i+n-a.topRight,s+a.topRight,a.topRight,0,-kt,!0),t.lineTo(i+a.topLeft,s)}function ae(t,e,i){i=i||(i=>t[i]<e);let s,n=t.length-1,o=0;for(;n-o>1;)s=o+n>>1,i(s)?o=s:n=s;return{lo:o,hi:n}}const re=(t,e,i)=>ae(t,i,(s=>t[s][e]<i)),le=(t,e,i)=>ae(t,i,(s=>t[s][e]>=i));function he(t,e,i){let s=0,n=t.length;for(;s<n&&t[s]<e;)s++;for(;n>s&&t[n-1]>i;)n--;return s>0||n<t.length?t.slice(s,n):t}const ce=["push","pop","shift","splice","unshift"];function de(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),ce.forEach((e=>{const i="_onData"+ht(e),s=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const n=s.apply(this,e);return t._chartjs.listeners.forEach((t=>{"function"==typeof t[i]&&t[i](...e)})),n}})})))}function ue(t,e){const i=t._chartjs;if(!i)return;const s=i.listeners,n=s.indexOf(e);-1!==n&&s.splice(n,1),s.length>0||(ce.forEach((e=>{delete t[e]})),delete t._chartjs)}function fe(t){const e=new Set;let i,s;for(i=0,s=t.length;i<s;++i)e.add(t[i]);return e.size===s?t:Array.from(e)}function ge(){return"undefined"!=typeof window&&"undefined"!=typeof document}function pe(t){let e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e}function me(t,e,i){let s;return"string"==typeof t?(s=parseInt(t,10),-1!==t.indexOf("%")&&(s=s/100*e.parentNode[i])):s=t,s}const xe=t=>window.getComputedStyle(t,null);function be(t,e){return xe(t).getPropertyValue(e)}const _e=["top","right","bottom","left"];function ye(t,e,i){const s={};i=i?"-"+i:"";for(let n=0;n<4;n++){const o=_e[n];s[o]=parseFloat(t[e+"-"+o+i])||0}return s.width=s.left+s.right,s.height=s.top+s.bottom,s}function ve(t,e){const{canvas:i,currentDevicePixelRatio:s}=e,n=xe(i),o="border-box"===n.boxSizing,a=ye(n,"padding"),r=ye(n,"border","width"),{x:l,y:h,box:c}=function(t,e){const i=t.native||t,s=i.touches,n=s&&s.length?s[0]:i,{offsetX:o,offsetY:a}=n;let r,l,h=!1;if(((t,e,i)=>(t>0||e>0)&&(!i||!i.shadowRoot))(o,a,i.target))r=o,l=a;else{const t=e.getBoundingClientRect();r=n.clientX-t.left,l=n.clientY-t.top,h=!0}return{x:r,y:l,box:h}}(t,i),d=a.left+(c&&r.left),u=a.top+(c&&r.top);let{width:f,height:g}=e;return o&&(f-=a.width+r.width,g-=a.height+r.height),{x:Math.round((l-d)/f*i.width/s),y:Math.round((h-u)/g*i.height/s)}}const we=t=>Math.round(10*t)/10;function Me(t,e,i,s){const n=xe(t),o=ye(n,"margin"),a=me(n.maxWidth,t,"clientWidth")||wt,r=me(n.maxHeight,t,"clientHeight")||wt,l=function(t,e,i){let s,n;if(void 0===e||void 0===i){const o=pe(t);if(o){const t=o.getBoundingClientRect(),a=xe(o),r=ye(a,"border","width"),l=ye(a,"padding");e=t.width-l.width-r.width,i=t.height-l.height-r.height,s=me(a.maxWidth,o,"clientWidth"),n=me(a.maxHeight,o,"clientHeight")}else e=t.clientWidth,i=t.clientHeight}return{width:e,height:i,maxWidth:s||wt,maxHeight:n||wt}}(t,e,i);let{width:h,height:c}=l;if("content-box"===n.boxSizing){const t=ye(n,"border","width"),e=ye(n,"padding");h-=e.width+t.width,c-=e.height+t.height}return h=Math.max(0,h-o.width),c=Math.max(0,s?Math.floor(h/s):c-o.height),h=we(Math.min(h,a,l.maxWidth)),c=we(Math.min(c,r,l.maxHeight)),h&&!c&&(c=we(h/2)),{width:h,height:c}}function ke(t,e,i){const s=e||1,n=Math.floor(t.height*s),o=Math.floor(t.width*s);t.height=n/s,t.width=o/s;const a=t.canvas;return a.style&&(i||!a.style.height&&!a.style.width)&&(a.style.height=`${t.height}px`,a.style.width=`${t.width}px`),(t.currentDevicePixelRatio!==s||a.height!==n||a.width!==o)&&(t.currentDevicePixelRatio=s,a.height=n,a.width=o,t.ctx.setTransform(s,0,0,s,0,0),!0)}const Se=function(){let t=!1;try{const e={get passive(){return t=!0,!1}};window.addEventListener("test",null,e),window.removeEventListener("test",null,e)}catch(t){}return t}();function Pe(t,e){const i=be(t,e),s=i&&i.match(/^(\d+)(\.\d+)?px$/);return s?+s[1]:void 0}function De(t,e){return"native"in t?{x:t.x,y:t.y}:ve(t,e)}function Ce(t,e,i,s){const{controller:n,data:o,_sorted:a}=t,r=n._cachedMeta.iScale;if(r&&e===r.axis&&"r"!==e&&a&&o.length){const t=r._reversePixels?le:re;if(!s)return t(o,e,i);if(n._sharedOptions){const s=o[0],n="function"==typeof s.getRange&&s.getRange(e);if(n){const s=t(o,e,i-n),a=t(o,e,i+n);return{lo:s.lo,hi:a.hi}}}}return{lo:0,hi:o.length-1}}function Oe(t,e,i,s,n){const o=t.getSortedVisibleDatasetMetas(),a=i[e];for(let t=0,i=o.length;t<i;++t){const{index:i,data:r}=o[t],{lo:l,hi:h}=Ce(o[t],e,a,n);for(let t=l;t<=h;++t){const e=r[t];e.skip||s(e,i,t)}}}function Ae(t,e,i,s){const n=[];if(!Jt(e,t.chartArea,t._minPadding))return n;return Oe(t,i,e,(function(t,i,o){t.inRange(e.x,e.y,s)&&n.push({element:t,datasetIndex:i,index:o})}),!0),n}function Te(t,e,i,s,n){let o=[];const a=function(t){const e=-1!==t.indexOf("x"),i=-1!==t.indexOf("y");return function(t,s){const n=e?Math.abs(t.x-s.x):0,o=i?Math.abs(t.y-s.y):0;return Math.sqrt(Math.pow(n,2)+Math.pow(o,2))}}(i);let r=Number.POSITIVE_INFINITY;return Oe(t,i,e,(function(i,l,h){const c=i.inRange(e.x,e.y,n);if(s&&!c)return;const d=i.getCenterPoint(n);if(!Jt(d,t.chartArea,t._minPadding)&&!c)return;const u=a(e,d);u<r?(o=[{element:i,datasetIndex:l,index:h}],r=u):u===r&&o.push({element:i,datasetIndex:l,index:h})})),o}function Le(t,e,i,s,n){return Jt(e,t.chartArea,t._minPadding)?"r"!==i||s?Te(t,e,i,s,n):function(t,e,i,s){let n=[];return Oe(t,i,e,(function(t,i,o){const{startAngle:a,endAngle:r}=t.getProps(["startAngle","endAngle"],s),{angle:l}=Bt(t,{x:e.x,y:e.y});Ht(l,a,r)&&n.push({element:t,datasetIndex:i,index:o})})),n}(t,e,i,n):[]}function Re(t,e,i,s){const n=De(e,t),o=[],a=i.axis,r="x"===a?"inXRange":"inYRange";let l=!1;return function(t,e){const i=t.getSortedVisibleDatasetMetas();let s,n,o;for(let t=0,a=i.length;t<a;++t){({index:s,data:n}=i[t]);for(let t=0,i=n.length;t<i;++t)o=n[t],o.skip||e(o,s,t)}}(t,((t,e,i)=>{t[r](n[a],s)&&o.push({element:t,datasetIndex:e,index:i}),t.inRange(n.x,n.y,s)&&(l=!0)})),i.intersect&&!l?[]:o}var Ee={modes:{index(t,e,i,s){const n=De(e,t),o=i.axis||"x",a=i.intersect?Ae(t,n,o,s):Le(t,n,o,!1,s),r=[];return a.length?(t.getSortedVisibleDatasetMetas().forEach((t=>{const e=a[0].index,i=t.data[e];i&&!i.skip&&r.push({element:i,datasetIndex:t.index,index:e})})),r):[]},dataset(t,e,i,s){const n=De(e,t),o=i.axis||"xy";let a=i.intersect?Ae(t,n,o,s):Le(t,n,o,!1,s);if(a.length>0){const e=a[0].datasetIndex,i=t.getDatasetMeta(e).data;a=[];for(let t=0;t<i.length;++t)a.push({element:i[t],datasetIndex:e,index:t})}return a},point:(t,e,i,s)=>Ae(t,De(e,t),i.axis||"xy",s),nearest:(t,e,i,s)=>Le(t,De(e,t),i.axis||"xy",i.intersect,s),x:(t,e,i,s)=>Re(t,e,{axis:"x",intersect:i.intersect},s),y:(t,e,i,s)=>Re(t,e,{axis:"y",intersect:i.intersect},s)}};const Ie=new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/),ze=new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);function Fe(t,e){const i=(""+t).match(Ie);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t}function Be(t,e){const i={},s=U(e),n=s?Object.keys(e):e,o=U(t)?s?i=>K(t[i],t[e[i]]):e=>t[e]:()=>t;for(const t of n)i[t]=+o(t)||0;return i}function Ve(t){return Be(t,{top:"y",right:"x",bottom:"y",left:"x"})}function We(t){return Be(t,["topLeft","topRight","bottomLeft","bottomRight"])}function Ne(t){const e=Ve(t);return e.width=e.left+e.right,e.height=e.top+e.bottom,e}function He(t,e){t=t||{},e=e||bt.font;let i=K(t.size,e.size);"string"==typeof i&&(i=parseInt(i,10));let s=K(t.style,e.style);s&&!(""+s).match(ze)&&(console.warn('Invalid font style specified: "'+s+'"'),s="");const n={family:K(t.family,e.family),lineHeight:Fe(K(t.lineHeight,e.lineHeight),i),size:i,style:s,weight:K(t.weight,e.weight),string:""};return n.string=Ut(n),n}function je(t,e,i,s){let n,o,a,r=!0;for(n=0,o=t.length;n<o;++n)if(a=t[n],void 0!==a&&(void 0!==e&&"function"==typeof a&&(a=a(e),r=!1),void 0!==i&&Y(a)&&(a=a[i%a.length],r=!1),void 0!==a))return s&&!r&&(s.cacheable=!1),a}function $e(t,e,i){const{min:s,max:n}=t,o=Z(e,(n-s)/2),a=(t,e)=>i&&0===t?0:t+e;return{min:a(s,-Math.abs(o)),max:a(n,o)}}function Ye(t,e){return Object.assign(Object.create(t),e)}const Ue=["left","top","right","bottom"];function Xe(t,e){return t.filter((t=>t.pos===e))}function qe(t,e){return t.filter((t=>-1===Ue.indexOf(t.pos)&&t.box.axis===e))}function Ke(t,e){return t.sort(((t,i)=>{const s=e?i:t,n=e?t:i;return s.weight===n.weight?s.index-n.index:s.weight-n.weight}))}function Ge(t,e){const i=function(t){const e={};for(const i of t){const{stack:t,pos:s,stackWeight:n}=i;if(!t||!Ue.includes(s))continue;const o=e[t]||(e[t]={count:0,placed:0,weight:0,size:0});o.count++,o.weight+=n}return e}(t),{vBoxMaxWidth:s,hBoxMaxHeight:n}=e;let o,a,r;for(o=0,a=t.length;o<a;++o){r=t[o];const{fullSize:a}=r.box,l=i[r.stack],h=l&&r.stackWeight/l.weight;r.horizontal?(r.width=h?h*s:a&&e.availableWidth,r.height=n):(r.width=s,r.height=h?h*n:a&&e.availableHeight)}return i}function Ze(t,e,i,s){return Math.max(t[i],e[i])+Math.max(t[s],e[s])}function Je(t,e){t.top=Math.max(t.top,e.top),t.left=Math.max(t.left,e.left),t.bottom=Math.max(t.bottom,e.bottom),t.right=Math.max(t.right,e.right)}function Qe(t,e,i,s){const{pos:n,box:o}=i,a=t.maxPadding;if(!U(n)){i.size&&(t[n]-=i.size);const e=s[i.stack]||{size:0,count:1};e.size=Math.max(e.size,i.horizontal?o.height:o.width),i.size=e.size/e.count,t[n]+=i.size}o.getPadding&&Je(a,o.getPadding());const r=Math.max(0,e.outerWidth-Ze(a,t,"left","right")),l=Math.max(0,e.outerHeight-Ze(a,t,"top","bottom")),h=r!==t.w,c=l!==t.h;return t.w=r,t.h=l,i.horizontal?{same:h,other:c}:{same:c,other:h}}function ti(t,e){const i=e.maxPadding;function s(t){const s={left:0,top:0,right:0,bottom:0};return t.forEach((t=>{s[t]=Math.max(e[t],i[t])})),s}return s(t?["left","right"]:["top","bottom"])}function ei(t,e,i,s){const n=[];let o,a,r,l,h,c;for(o=0,a=t.length,h=0;o<a;++o){r=t[o],l=r.box,l.update(r.width||e.w,r.height||e.h,ti(r.horizontal,e));const{same:a,other:d}=Qe(e,i,r,s);h|=a&&n.length,c=c||d,l.fullSize||n.push(r)}return h&&ei(n,e,i,s)||c}function ii(t,e,i,s,n){t.top=i,t.left=e,t.right=e+s,t.bottom=i+n,t.width=s,t.height=n}function si(t,e,i,s){const n=i.padding;let{x:o,y:a}=e;for(const r of t){const t=r.box,l=s[r.stack]||{count:1,placed:0,weight:1},h=r.stackWeight/l.weight||1;if(r.horizontal){const s=e.w*h,o=l.size||t.height;ct(l.start)&&(a=l.start),t.fullSize?ii(t,n.left,a,i.outerWidth-n.right-n.left,o):ii(t,e.left+l.placed,a,s,o),l.start=a,l.placed+=s,a=t.bottom}else{const s=e.h*h,a=l.size||t.width;ct(l.start)&&(o=l.start),t.fullSize?ii(t,o,n.top,a,i.outerHeight-n.bottom-n.top):ii(t,o,e.top+l.placed,a,s),l.start=o,l.placed+=s,o=t.right}}e.x=o,e.y=a}bt.set("layout",{autoPadding:!0,padding:{top:0,right:0,bottom:0,left:0}});var ni={addBox(t,e){t.boxes||(t.boxes=[]),e.fullSize=e.fullSize||!1,e.position=e.position||"top",e.weight=e.weight||0,e._layers=e._layers||function(){return[{z:0,draw(t){e.draw(t)}}]},t.boxes.push(e)},removeBox(t,e){const i=t.boxes?t.boxes.indexOf(e):-1;-1!==i&&t.boxes.splice(i,1)},configure(t,e,i){e.fullSize=i.fullSize,e.position=i.position,e.weight=i.weight},update(t,e,i,s){if(!t)return;const n=Ne(t.options.layout.padding),o=Math.max(e-n.width,0),a=Math.max(i-n.height,0),r=function(t){const e=function(t){const e=[];let i,s,n,o,a,r;for(i=0,s=(t||[]).length;i<s;++i)n=t[i],({position:o,options:{stack:a,stackWeight:r=1}}=n),e.push({index:i,box:n,pos:o,horizontal:n.isHorizontal(),weight:n.weight,stack:a&&o+a,stackWeight:r});return e}(t),i=Ke(e.filter((t=>t.box.fullSize)),!0),s=Ke(Xe(e,"left"),!0),n=Ke(Xe(e,"right")),o=Ke(Xe(e,"top"),!0),a=Ke(Xe(e,"bottom")),r=qe(e,"x"),l=qe(e,"y");return{fullSize:i,leftAndTop:s.concat(o),rightAndBottom:n.concat(l).concat(a).concat(r),chartArea:Xe(e,"chartArea"),vertical:s.concat(n).concat(l),horizontal:o.concat(a).concat(r)}}(t.boxes),l=r.vertical,h=r.horizontal;Q(t.boxes,(t=>{"function"==typeof t.beforeLayout&&t.beforeLayout()}));const c=l.reduce(((t,e)=>e.box.options&&!1===e.box.options.display?t:t+1),0)||1,d=Object.freeze({outerWidth:e,outerHeight:i,padding:n,availableWidth:o,availableHeight:a,vBoxMaxWidth:o/2/c,hBoxMaxHeight:a/2}),u=Object.assign({},n);Je(u,Ne(s));const f=Object.assign({maxPadding:u,w:o,h:a,x:n.left,y:n.top},n),g=Ge(l.concat(h),d);ei(r.fullSize,f,d,g),ei(l,f,d,g),ei(h,f,d,g)&&ei(l,f,d,g),function(t){const e=t.maxPadding;function i(i){const s=Math.max(e[i]-t[i],0);return t[i]+=s,s}t.y+=i("top"),t.x+=i("left"),i("right"),i("bottom")}(f),si(r.leftAndTop,f,d,g),f.x+=f.w,f.y+=f.h,si(r.rightAndBottom,f,d,g),t.chartArea={left:f.left,top:f.top,right:f.left+f.w,bottom:f.top+f.h,height:f.h,width:f.w},Q(r.chartArea,(e=>{const i=e.box;Object.assign(i,t.chartArea),i.update(f.w,f.h,{left:0,top:0,right:0,bottom:0})}))}};function oi(t,e=[""],i=t,s,n=(()=>t[0])){ct(s)||(s=mi("_fallback",t));const o={[Symbol.toStringTag]:"Object",_cacheable:!0,_scopes:t,_rootScopes:i,_fallback:s,_getTarget:n,override:n=>oi([n,...t],e,i,s)};return new Proxy(o,{deleteProperty:(e,i)=>(delete e[i],delete e._keys,delete t[0][i],!0),get:(i,s)=>ci(i,s,(()=>function(t,e,i,s){let n;for(const o of e)if(n=mi(li(o,t),i),ct(n))return hi(t,n)?gi(i,s,t,n):n}(s,e,t,i))),getOwnPropertyDescriptor:(t,e)=>Reflect.getOwnPropertyDescriptor(t._scopes[0],e),getPrototypeOf:()=>Reflect.getPrototypeOf(t[0]),has:(t,e)=>xi(t).includes(e),ownKeys:t=>xi(t),set(t,e,i){const s=t._storage||(t._storage=n());return t[e]=s[e]=i,delete t._keys,!0}})}function ai(t,e,i,s){const n={_cacheable:!1,_proxy:t,_context:e,_subProxy:i,_stack:new Set,_descriptors:ri(t,s),setContext:e=>ai(t,e,i,s),override:n=>ai(t.override(n),e,i,s)};return new Proxy(n,{deleteProperty:(e,i)=>(delete e[i],delete t[i],!0),get:(t,e,i)=>ci(t,e,(()=>function(t,e,i){const{_proxy:s,_context:n,_subProxy:o,_descriptors:a}=t;let r=s[e];dt(r)&&a.isScriptable(e)&&(r=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_stack:r}=i;if(r.has(t))throw new Error("Recursion detected: "+Array.from(r).join("->")+"->"+t);r.add(t),e=e(o,a||s),r.delete(t),hi(t,e)&&(e=gi(n._scopes,n,t,e));return e}(e,r,t,i));Y(r)&&r.length&&(r=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_descriptors:r}=i;if(ct(o.index)&&s(t))e=e[o.index%e.length];else if(U(e[0])){const i=e,s=n._scopes.filter((t=>t!==i));e=[];for(const l of i){const i=gi(s,n,t,l);e.push(ai(i,o,a&&a[t],r))}}return e}(e,r,t,a.isIndexable));hi(e,r)&&(r=ai(r,n,o&&o[e],a));return r}(t,e,i))),getOwnPropertyDescriptor:(e,i)=>e._descriptors.allKeys?Reflect.has(t,i)?{enumerable:!0,configurable:!0}:void 0:Reflect.getOwnPropertyDescriptor(t,i),getPrototypeOf:()=>Reflect.getPrototypeOf(t),has:(e,i)=>Reflect.has(t,i),ownKeys:()=>Reflect.ownKeys(t),set:(e,i,s)=>(t[i]=s,delete e[i],!0)})}function ri(t,e={scriptable:!0,indexable:!0}){const{_scriptable:i=e.scriptable,_indexable:s=e.indexable,_allKeys:n=e.allKeys}=t;return{allKeys:n,scriptable:i,indexable:s,isScriptable:dt(i)?i:()=>i,isIndexable:dt(s)?s:()=>s}}const li=(t,e)=>t?t+ht(e):e,hi=(t,e)=>U(e)&&"adapters"!==t&&(null===Object.getPrototypeOf(e)||e.constructor===Object);function ci(t,e,i){if(Object.prototype.hasOwnProperty.call(t,e))return t[e];const s=i();return t[e]=s,s}function di(t,e,i){return dt(t)?t(e,i):t}const ui=(t,e)=>!0===t?e:"string"==typeof t?lt(e,t):void 0;function fi(t,e,i,s,n){for(const o of e){const e=ui(i,o);if(e){t.add(e);const o=di(e._fallback,i,n);if(ct(o)&&o!==i&&o!==s)return o}else if(!1===e&&ct(s)&&i!==s)return null}return!1}function gi(t,e,i,s){const n=e._rootScopes,o=di(e._fallback,i,s),a=[...t,...n],r=new Set;r.add(s);let l=pi(r,a,i,o||i,s);return null!==l&&((!ct(o)||o===i||(l=pi(r,a,o,l,s),null!==l))&&oi(Array.from(r),[""],n,o,(()=>function(t,e,i){const s=t._getTarget();e in s||(s[e]={});const n=s[e];if(Y(n)&&U(i))return i;return n}(e,i,s))))}function pi(t,e,i,s,n){for(;i;)i=fi(t,e,i,s,n);return i}function mi(t,e){for(const i of e){if(!i)continue;const e=i[t];if(ct(e))return e}}function xi(t){let e=t._keys;return e||(e=t._keys=function(t){const e=new Set;for(const i of t)for(const t of Object.keys(i).filter((t=>!t.startsWith("_"))))e.add(t);return Array.from(e)}(t._scopes)),e}const bi=Number.EPSILON||1e-14,_i=(t,e)=>e<t.length&&!t[e].skip&&t[e],yi=t=>"x"===t?"y":"x";function vi(t,e,i,s){const n=t.skip?e:t,o=e,a=i.skip?e:i,r=Vt(o,n),l=Vt(a,o);let h=r/(r+l),c=l/(r+l);h=isNaN(h)?0:h,c=isNaN(c)?0:c;const d=s*h,u=s*c;return{previous:{x:o.x-d*(a.x-n.x),y:o.y-d*(a.y-n.y)},next:{x:o.x+u*(a.x-n.x),y:o.y+u*(a.y-n.y)}}}function wi(t,e="x"){const i=yi(e),s=t.length,n=Array(s).fill(0),o=Array(s);let a,r,l,h=_i(t,0);for(a=0;a<s;++a)if(r=l,l=h,h=_i(t,a+1),l){if(h){const t=h[e]-l[e];n[a]=0!==t?(h[i]-l[i])/t:0}o[a]=r?h?Ct(n[a-1])!==Ct(n[a])?0:(n[a-1]+n[a])/2:n[a-1]:n[a]}!function(t,e,i){const s=t.length;let n,o,a,r,l,h=_i(t,0);for(let c=0;c<s-1;++c)l=h,h=_i(t,c+1),l&&h&&(Lt(e[c],0,bi)?i[c]=i[c+1]=0:(n=i[c]/e[c],o=i[c+1]/e[c],r=Math.pow(n,2)+Math.pow(o,2),r<=9||(a=3/Math.sqrt(r),i[c]=n*a*e[c],i[c+1]=o*a*e[c])))}(t,n,o),function(t,e,i="x"){const s=yi(i),n=t.length;let o,a,r,l=_i(t,0);for(let h=0;h<n;++h){if(a=r,r=l,l=_i(t,h+1),!r)continue;const n=r[i],c=r[s];a&&(o=(n-a[i])/3,r[`cp1${i}`]=n-o,r[`cp1${s}`]=c-o*e[h]),l&&(o=(l[i]-n)/3,r[`cp2${i}`]=n+o,r[`cp2${s}`]=c+o*e[h])}}(t,o,e)}function Mi(t,e,i){return Math.max(Math.min(t,i),e)}function ki(t,e,i,s,n){let o,a,r,l;if(e.spanGaps&&(t=t.filter((t=>!t.skip))),"monotone"===e.cubicInterpolationMode)wi(t,n);else{let i=s?t[t.length-1]:t[0];for(o=0,a=t.length;o<a;++o)r=t[o],l=vi(i,r,t[Math.min(o+1,a-(s?0:1))%a],e.tension),r.cp1x=l.previous.x,r.cp1y=l.previous.y,r.cp2x=l.next.x,r.cp2y=l.next.y,i=r}e.capBezierPoints&&function(t,e){let i,s,n,o,a,r=Jt(t[0],e);for(i=0,s=t.length;i<s;++i)a=o,o=r,r=i<s-1&&Jt(t[i+1],e),o&&(n=t[i],a&&(n.cp1x=Mi(n.cp1x,e.left,e.right),n.cp1y=Mi(n.cp1y,e.top,e.bottom)),r&&(n.cp2x=Mi(n.cp2x,e.left,e.right),n.cp2y=Mi(n.cp2y,e.top,e.bottom)))}(t,i)}const Si=t=>0===t||1===t,Pi=(t,e,i)=>-Math.pow(2,10*(t-=1))*Math.sin((t-e)*yt/i),Di=(t,e,i)=>Math.pow(2,-10*t)*Math.sin((t-e)*yt/i)+1,Ci={linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>-t*(t-2),easeInOutQuad:t=>(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1),easeInCubic:t=>t*t*t,easeOutCubic:t=>(t-=1)*t*t+1,easeInOutCubic:t=>(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2),easeInQuart:t=>t*t*t*t,easeOutQuart:t=>-((t-=1)*t*t*t-1),easeInOutQuart:t=>(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2),easeInQuint:t=>t*t*t*t*t,easeOutQuint:t=>(t-=1)*t*t*t*t+1,easeInOutQuint:t=>(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2),easeInSine:t=>1-Math.cos(t*kt),easeOutSine:t=>Math.sin(t*kt),easeInOutSine:t=>-.5*(Math.cos(_t*t)-1),easeInExpo:t=>0===t?0:Math.pow(2,10*(t-1)),easeOutExpo:t=>1===t?1:1-Math.pow(2,-10*t),easeInOutExpo:t=>Si(t)?t:t<.5?.5*Math.pow(2,10*(2*t-1)):.5*(2-Math.pow(2,-10*(2*t-1))),easeInCirc:t=>t>=1?t:-(Math.sqrt(1-t*t)-1),easeOutCirc:t=>Math.sqrt(1-(t-=1)*t),easeInOutCirc:t=>(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1),easeInElastic:t=>Si(t)?t:Pi(t,.075,.3),easeOutElastic:t=>Si(t)?t:Di(t,.075,.3),easeInOutElastic(t){const e=.1125;return Si(t)?t:t<.5?.5*Pi(2*t,e,.45):.5+.5*Di(2*t-1,e,.45)},easeInBack(t){const e=1.70158;return t*t*((e+1)*t-e)},easeOutBack(t){const e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack(t){let e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:t=>1-Ci.easeOutBounce(1-t),easeOutBounce(t){const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375},easeInOutBounce:t=>t<.5?.5*Ci.easeInBounce(2*t):.5*Ci.easeOutBounce(2*t-1)+.5};function Oi(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:t.y+i*(e.y-t.y)}}function Ai(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:"middle"===s?i<.5?t.y:e.y:"after"===s?i<1?t.y:e.y:i>0?e.y:t.y}}function Ti(t,e,i,s){const n={x:t.cp2x,y:t.cp2y},o={x:e.cp1x,y:e.cp1y},a=Oi(t,n,i),r=Oi(n,o,i),l=Oi(o,e,i),h=Oi(a,r,i),c=Oi(r,l,i);return Oi(h,c,i)}const Li=new Map;function Ri(t,e,i){return function(t,e){e=e||{};const i=t+JSON.stringify(e);let s=Li.get(i);return s||(s=new Intl.NumberFormat(t,e),Li.set(i,s)),s}(e,i).format(t)}function Ei(t,e,i){return t?function(t,e){return{x:i=>t+t+e-i,setWidth(t){e=t},textAlign:t=>"center"===t?t:"right"===t?"left":"right",xPlus:(t,e)=>t-e,leftForLtr:(t,e)=>t-e}}(e,i):{x:t=>t,setWidth(t){},textAlign:t=>t,xPlus:(t,e)=>t+e,leftForLtr:(t,e)=>t}}function Ii(t,e){let i,s;"ltr"!==e&&"rtl"!==e||(i=t.canvas.style,s=[i.getPropertyValue("direction"),i.getPropertyPriority("direction")],i.setProperty("direction",e,"important"),t.prevTextDirection=s)}function zi(t,e){void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}function Fi(t){return"angle"===t?{between:Ht,compare:Wt,normalize:Nt}:{between:Yt,compare:(t,e)=>t-e,normalize:t=>t}}function Bi({start:t,end:e,count:i,loop:s,style:n}){return{start:t%i,end:e%i,loop:s&&(e-t+1)%i==0,style:n}}function Vi(t,e,i){if(!i)return[t];const{property:s,start:n,end:o}=i,a=e.length,{compare:r,between:l,normalize:h}=Fi(s),{start:c,end:d,loop:u,style:f}=function(t,e,i){const{property:s,start:n,end:o}=i,{between:a,normalize:r}=Fi(s),l=e.length;let h,c,{start:d,end:u,loop:f}=t;if(f){for(d+=l,u+=l,h=0,c=l;h<c&&a(r(e[d%l][s]),n,o);++h)d--,u--;d%=l,u%=l}return u<d&&(u+=l),{start:d,end:u,loop:f,style:t.style}}(t,e,i),g=[];let p,m,x,b=!1,_=null;const y=()=>b||l(n,x,p)&&0!==r(n,x),v=()=>!b||0===r(o,p)||l(o,x,p);for(let t=c,i=c;t<=d;++t)m=e[t%a],m.skip||(p=h(m[s]),p!==x&&(b=l(p,n,o),null===_&&y()&&(_=0===r(p,n)?t:i),null!==_&&v()&&(g.push(Bi({start:_,end:t,loop:u,count:a,style:f})),_=null),i=t,x=p));return null!==_&&g.push(Bi({start:_,end:d,loop:u,count:a,style:f})),g}function Wi(t,e){const i=[],s=t.segments;for(let n=0;n<s.length;n++){const o=Vi(s[n],t.points,e);o.length&&i.push(...o)}return i}function Ni(t,e){const i=t.points,s=t.options.spanGaps,n=i.length;if(!n)return[];const o=!!t._loop,{start:a,end:r}=function(t,e,i,s){let n=0,o=e-1;if(i&&!s)for(;n<e&&!t[n].skip;)n++;for(;n<e&&t[n].skip;)n++;for(n%=e,i&&(o+=n);o>n&&t[o%e].skip;)o--;return o%=e,{start:n,end:o}}(i,n,o,s);if(!0===s)return Hi(t,[{start:a,end:r,loop:o}],i,e);return Hi(t,function(t,e,i,s){const n=t.length,o=[];let a,r=e,l=t[e];for(a=e+1;a<=i;++a){const i=t[a%n];i.skip||i.stop?l.skip||(s=!1,o.push({start:e%n,end:(a-1)%n,loop:s}),e=r=i.stop?a:null):(r=a,l.skip&&(e=a)),l=i}return null!==r&&o.push({start:e%n,end:r%n,loop:s}),o}(i,a,r<a?r+n:r,!!t._fullLoop&&0===a&&r===n-1),i,e)}function Hi(t,e,i,s){return s&&s.setContext&&i?function(t,e,i,s){const n=t._chart.getContext(),o=ji(t.options),{_datasetIndex:a,options:{spanGaps:r}}=t,l=i.length,h=[];let c=o,d=e[0].start,u=d;function f(t,e,s,n){const o=r?-1:1;if(t!==e){for(t+=l;i[t%l].skip;)t-=o;for(;i[e%l].skip;)e+=o;t%l!=e%l&&(h.push({start:t%l,end:e%l,loop:s,style:n}),c=n,d=e%l)}}for(const t of e){d=r?d:t.start;let e,o=i[d%l];for(u=d+1;u<=t.end;u++){const r=i[u%l];e=ji(s.setContext(Ye(n,{type:"segment",p0:o,p1:r,p0DataIndex:(u-1)%l,p1DataIndex:u%l,datasetIndex:a}))),$i(e,c)&&f(d,u-1,t.loop,c),o=r,c=e}d<u-1&&f(d,u-1,t.loop,c)}return h}(t,e,i,s):e}function ji(t){return{backgroundColor:t.backgroundColor,borderCapStyle:t.borderCapStyle,borderDash:t.borderDash,borderDashOffset:t.borderDashOffset,borderJoinStyle:t.borderJoinStyle,borderWidth:t.borderWidth,borderColor:t.borderColor}}function $i(t,e){return e&&JSON.stringify(t)!==JSON.stringify(e)}var Yi=Object.freeze({__proto__:null,easingEffects:Ci,color:W,getHoverColor:N,noop:H,uid:j,isNullOrUndef:$,isArray:Y,isObject:U,isFinite:X,finiteOrDefault:q,valueOrDefault:K,toPercentage:G,toDimension:Z,callback:J,each:Q,_elementsEqual:tt,clone:et,_merger:st,merge:nt,mergeIf:ot,_mergerIf:at,_deprecated:function(t,e,i,s){void 0!==e&&console.warn(t+': "'+i+'" is deprecated. Please use "'+s+'" instead')},resolveObjectKey:lt,_capitalize:ht,defined:ct,isFunction:dt,setsEqual:ut,_isClickEvent:ft,toFontString:Ut,_measureText:Xt,_longestText:qt,_alignPixel:Kt,clearCanvas:Gt,drawPoint:Zt,_isPointInArea:Jt,clipArea:Qt,unclipArea:te,_steppedLineTo:ee,_bezierCurveTo:ie,renderText:se,addRoundedRectPath:oe,_lookup:ae,_lookupByKey:re,_rlookupByKey:le,_filterBetween:he,listenArrayEvents:de,unlistenArrayEvents:ue,_arrayUnique:fe,_createResolver:oi,_attachContext:ai,_descriptors:ri,splineCurve:vi,splineCurveMonotone:wi,_updateBezierControlPoints:ki,_isDomSupported:ge,_getParentNode:pe,getStyle:be,getRelativePosition:ve,getMaximumSize:Me,retinaScale:ke,supportsEventListenerOptions:Se,readUsedSize:Pe,fontString:function(t,e,i){return e+" "+t+"px "+i},requestAnimFrame:t,throttled:e,debounce:i,_toLeftRightCenter:s,_alignStartEnd:n,_textX:o,_pointInLine:Oi,_steppedInterpolation:Ai,_bezierInterpolation:Ti,formatNumber:Ri,toLineHeight:Fe,_readValueToProps:Be,toTRBL:Ve,toTRBLCorners:We,toPadding:Ne,toFont:He,resolve:je,_addGrace:$e,createContext:Ye,PI:_t,TAU:yt,PITAU:vt,INFINITY:wt,RAD_PER_DEG:Mt,HALF_PI:kt,QUARTER_PI:St,TWO_THIRDS_PI:Pt,log10:Dt,sign:Ct,niceNum:Ot,_factorize:At,isNumber:Tt,almostEquals:Lt,almostWhole:Rt,_setMinAndMaxByKey:Et,toRadians:It,toDegrees:zt,_decimalPlaces:Ft,getAngleFromPoint:Bt,distanceBetweenPoints:Vt,_angleDiff:Wt,_normalizeAngle:Nt,_angleBetween:Ht,_limitValue:jt,_int16Range:$t,_isBetween:Yt,getRtlAdapter:Ei,overrideTextDirection:Ii,restoreTextDirection:zi,_boundSegment:Vi,_boundSegments:Wi,_computeSegments:Ni});class Ui{acquireContext(t,e){}releaseContext(t){return!1}addEventListener(t,e,i){}removeEventListener(t,e,i){}getDevicePixelRatio(){return 1}getMaximumSize(t,e,i,s){return e=Math.max(0,e||t.width),i=i||t.height,{width:e,height:Math.max(0,s?Math.floor(e/s):i)}}isAttached(t){return!0}updateConfig(t){}}class Xi extends Ui{acquireContext(t){return t&&t.getContext&&t.getContext("2d")||null}updateConfig(t){t.options.animation=!1}}const qi={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},Ki=t=>null===t||""===t;const Gi=!!Se&&{passive:!0};function Zi(t,e,i){t.canvas.removeEventListener(e,i,Gi)}function Ji(t,e){for(const i of t)if(i===e||i.contains(e))return!0}function Qi(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||Ji(i.addedNodes,s),e=e&&!Ji(i.removedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}function ts(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||Ji(i.removedNodes,s),e=e&&!Ji(i.addedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}const es=new Map;let is=0;function ss(){const t=window.devicePixelRatio;t!==is&&(is=t,es.forEach(((e,i)=>{i.currentDevicePixelRatio!==t&&e()})))}function ns(t,i,s){const n=t.canvas,o=n&&pe(n);if(!o)return;const a=e(((t,e)=>{const i=o.clientWidth;s(t,e),i<o.clientWidth&&s()}),window),r=new ResizeObserver((t=>{const e=t[0],i=e.contentRect.width,s=e.contentRect.height;0===i&&0===s||a(i,s)}));return r.observe(o),function(t,e){es.size||window.addEventListener("resize",ss),es.set(t,e)}(t,a),r}function os(t,e,i){i&&i.disconnect(),"resize"===e&&function(t){es.delete(t),es.size||window.removeEventListener("resize",ss)}(t)}function as(t,i,s){const n=t.canvas,o=e((e=>{null!==t.ctx&&s(function(t,e){const i=qi[t.type]||t.type,{x:s,y:n}=ve(t,e);return{type:i,chart:e,native:t,x:void 0!==s?s:null,y:void 0!==n?n:null}}(e,t))}),t,(t=>{const e=t[0];return[e,e.offsetX,e.offsetY]}));return function(t,e,i){t.addEventListener(e,i,Gi)}(n,i,o),o}class rs extends Ui{acquireContext(t,e){const i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){const i=t.style,s=t.getAttribute("height"),n=t.getAttribute("width");if(t.$chartjs={initial:{height:s,width:n,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",i.boxSizing=i.boxSizing||"border-box",Ki(n)){const e=Pe(t,"width");void 0!==e&&(t.width=e)}if(Ki(s))if(""===t.style.height)t.height=t.width/(e||2);else{const e=Pe(t,"height");void 0!==e&&(t.height=e)}}(t,e),i):null}releaseContext(t){const e=t.canvas;if(!e.$chartjs)return!1;const i=e.$chartjs.initial;["height","width"].forEach((t=>{const s=i[t];$(s)?e.removeAttribute(t):e.setAttribute(t,s)}));const s=i.style||{};return Object.keys(s).forEach((t=>{e.style[t]=s[t]})),e.width=e.width,delete e.$chartjs,!0}addEventListener(t,e,i){this.removeEventListener(t,e);const s=t.$proxies||(t.$proxies={}),n={attach:Qi,detach:ts,resize:ns}[e]||as;s[e]=n(t,e,i)}removeEventListener(t,e){const i=t.$proxies||(t.$proxies={}),s=i[e];if(!s)return;({attach:os,detach:os,resize:os}[e]||Zi)(t,e,s),i[e]=void 0}getDevicePixelRatio(){return window.devicePixelRatio}getMaximumSize(t,e,i,s){return Me(t,e,i,s)}isAttached(t){const e=pe(t);return!(!e||!e.isConnected)}}function ls(t){return!ge()||"undefined"!=typeof OffscreenCanvas&&t instanceof OffscreenCanvas?Xi:rs}var hs=Object.freeze({__proto__:null,_detectPlatform:ls,BasePlatform:Ui,BasicPlatform:Xi,DomPlatform:rs});const cs="transparent",ds={boolean:(t,e,i)=>i>.5?e:t,color(t,e,i){const s=W(t||cs),n=s.valid&&W(e||cs);return n&&n.valid?n.mix(s,i).hexString():e},number:(t,e,i)=>t+(e-t)*i};class us{constructor(t,e,i,s){const n=e[i];s=je([t.to,s,n,t.from]);const o=je([t.from,n,s]);this._active=!0,this._fn=t.fn||ds[t.type||typeof o],this._easing=Ci[t.easing]||Ci.linear,this._start=Math.floor(Date.now()+(t.delay||0)),this._duration=this._total=Math.floor(t.duration),this._loop=!!t.loop,this._target=e,this._prop=i,this._from=o,this._to=s,this._promises=void 0}active(){return this._active}update(t,e,i){if(this._active){this._notify(!1);const s=this._target[this._prop],n=i-this._start,o=this._duration-n;this._start=i,this._duration=Math.floor(Math.max(o,t.duration)),this._total+=n,this._loop=!!t.loop,this._to=je([t.to,e,s,t.from]),this._from=je([t.from,s,e])}}cancel(){this._active&&(this.tick(Date.now()),this._active=!1,this._notify(!1))}tick(t){const e=t-this._start,i=this._duration,s=this._prop,n=this._from,o=this._loop,a=this._to;let r;if(this._active=n!==a&&(o||e<i),!this._active)return this._target[s]=a,void this._notify(!0);e<0?this._target[s]=n:(r=e/i%2,r=o&&r>1?2-r:r,r=this._easing(Math.min(1,Math.max(0,r))),this._target[s]=this._fn(n,a,r))}wait(){const t=this._promises||(this._promises=[]);return new Promise(((e,i)=>{t.push({res:e,rej:i})}))}_notify(t){const e=t?"res":"rej",i=this._promises||[];for(let t=0;t<i.length;t++)i[t][e]()}}bt.set("animation",{delay:void 0,duration:1e3,easing:"easeOutQuart",fn:void 0,from:void 0,loop:void 0,to:void 0,type:void 0});const fs=Object.keys(bt.animation);bt.describe("animation",{_fallback:!1,_indexable:!1,_scriptable:t=>"onProgress"!==t&&"onComplete"!==t&&"fn"!==t}),bt.set("animations",{colors:{type:"color",properties:["color","borderColor","backgroundColor"]},numbers:{type:"number",properties:["x","y","borderWidth","radius","tension"]}}),bt.describe("animations",{_fallback:"animation"}),bt.set("transitions",{active:{animation:{duration:400}},resize:{animation:{duration:0}},show:{animations:{colors:{from:"transparent"},visible:{type:"boolean",duration:0}}},hide:{animations:{colors:{to:"transparent"},visible:{type:"boolean",easing:"linear",fn:t=>0|t}}}});class gs{constructor(t,e){this._chart=t,this._properties=new Map,this.configure(e)}configure(t){if(!U(t))return;const e=this._properties;Object.getOwnPropertyNames(t).forEach((i=>{const s=t[i];if(!U(s))return;const n={};for(const t of fs)n[t]=s[t];(Y(s.properties)&&s.properties||[i]).forEach((t=>{t!==i&&e.has(t)||e.set(t,n)}))}))}_animateOptions(t,e){const i=e.options,s=function(t,e){if(!e)return;let i=t.options;if(!i)return void(t.options=e);i.$shared&&(t.options=i=Object.assign({},i,{$shared:!1,$animations:{}}));return i}(t,i);if(!s)return[];const n=this._createAnimations(s,i);return i.$shared&&function(t,e){const i=[],s=Object.keys(e);for(let e=0;e<s.length;e++){const n=t[s[e]];n&&n.active()&&i.push(n.wait())}return Promise.all(i)}(t.options.$animations,i).then((()=>{t.options=i}),(()=>{})),n}_createAnimations(t,e){const i=this._properties,s=[],n=t.$animations||(t.$animations={}),o=Object.keys(e),a=Date.now();let r;for(r=o.length-1;r>=0;--r){const l=o[r];if("$"===l.charAt(0))continue;if("options"===l){s.push(...this._animateOptions(t,e));continue}const h=e[l];let c=n[l];const d=i.get(l);if(c){if(d&&c.active()){c.update(d,h,a);continue}c.cancel()}d&&d.duration?(n[l]=c=new us(d,t,l,h),s.push(c)):t[l]=h}return s}update(t,e){if(0===this._properties.size)return void Object.assign(t,e);const i=this._createAnimations(t,e);return i.length?(a.add(this._chart,i),!0):void 0}}function ps(t,e){const i=t&&t.options||{},s=i.reverse,n=void 0===i.min?e:0,o=void 0===i.max?e:0;return{start:s?o:n,end:s?n:o}}function ms(t,e){const i=[],s=t._getSortedDatasetMetas(e);let n,o;for(n=0,o=s.length;n<o;++n)i.push(s[n].index);return i}function xs(t,e,i,s={}){const n=t.keys,o="single"===s.mode;let a,r,l,h;if(null!==e){for(a=0,r=n.length;a<r;++a){if(l=+n[a],l===i){if(s.all)continue;break}h=t.values[l],X(h)&&(o||0===e||Ct(e)===Ct(h))&&(e+=h)}return e}}function bs(t,e){const i=t&&t.options.stacked;return i||void 0===i&&void 0!==e.stack}function _s(t,e,i){const s=t[e]||(t[e]={});return s[i]||(s[i]={})}function ys(t,e,i,s){for(const n of e.getMatchingVisibleMetas(s).reverse()){const e=t[n.index];if(i&&e>0||!i&&e<0)return n.index}return null}function vs(t,e){const{chart:i,_cachedMeta:s}=t,n=i._stacks||(i._stacks={}),{iScale:o,vScale:a,index:r}=s,l=o.axis,h=a.axis,c=function(t,e,i){return`${t.id}.${e.id}.${i.stack||i.type}`}(o,a,s),d=e.length;let u;for(let t=0;t<d;++t){const i=e[t],{[l]:o,[h]:d}=i;u=(i._stacks||(i._stacks={}))[h]=_s(n,c,o),u[r]=d,u._top=ys(u,a,!0,s.type),u._bottom=ys(u,a,!1,s.type)}}function ws(t,e){const i=t.scales;return Object.keys(i).filter((t=>i[t].axis===e)).shift()}function Ms(t,e){const i=t.controller.index,s=t.vScale&&t.vScale.axis;if(s){e=e||t._parsed;for(const t of e){const e=t._stacks;if(!e||void 0===e[s]||void 0===e[s][i])return;delete e[s][i]}}}const ks=t=>"reset"===t||"none"===t,Ss=(t,e)=>e?t:Object.assign({},t);class Ps{constructor(t,e){this.chart=t,this._ctx=t.ctx,this.index=e,this._cachedDataOpts={},this._cachedMeta=this.getMeta(),this._type=this._cachedMeta.type,this.options=void 0,this._parsing=!1,this._data=void 0,this._objectData=void 0,this._sharedOptions=void 0,this._drawStart=void 0,this._drawCount=void 0,this.enableOptionSharing=!1,this.$context=void 0,this._syncList=[],this.initialize()}initialize(){const t=this._cachedMeta;this.configure(),this.linkScales(),t._stacked=bs(t.vScale,t),this.addElements()}updateIndex(t){this.index!==t&&Ms(this._cachedMeta),this.index=t}linkScales(){const t=this.chart,e=this._cachedMeta,i=this.getDataset(),s=(t,e,i,s)=>"x"===t?e:"r"===t?s:i,n=e.xAxisID=K(i.xAxisID,ws(t,"x")),o=e.yAxisID=K(i.yAxisID,ws(t,"y")),a=e.rAxisID=K(i.rAxisID,ws(t,"r")),r=e.indexAxis,l=e.iAxisID=s(r,n,o,a),h=e.vAxisID=s(r,o,n,a);e.xScale=this.getScaleForId(n),e.yScale=this.getScaleForId(o),e.rScale=this.getScaleForId(a),e.iScale=this.getScaleForId(l),e.vScale=this.getScaleForId(h)}getDataset(){return this.chart.data.datasets[this.index]}getMeta(){return this.chart.getDatasetMeta(this.index)}getScaleForId(t){return this.chart.scales[t]}_getOtherScale(t){const e=this._cachedMeta;return t===e.iScale?e.vScale:e.iScale}reset(){this._update("reset")}_destroy(){const t=this._cachedMeta;this._data&&ue(this._data,this),t._stacked&&Ms(t)}_dataCheck(){const t=this.getDataset(),e=t.data||(t.data=[]),i=this._data;if(U(e))this._data=function(t){const e=Object.keys(t),i=new Array(e.length);let s,n,o;for(s=0,n=e.length;s<n;++s)o=e[s],i[s]={x:o,y:t[o]};return i}(e);else if(i!==e){if(i){ue(i,this);const t=this._cachedMeta;Ms(t),t._parsed=[]}e&&Object.isExtensible(e)&&de(e,this),this._syncList=[],this._data=e}}addElements(){const t=this._cachedMeta;this._dataCheck(),this.datasetElementType&&(t.dataset=new this.datasetElementType)}buildOrUpdateElements(t){const e=this._cachedMeta,i=this.getDataset();let s=!1;this._dataCheck();const n=e._stacked;e._stacked=bs(e.vScale,e),e.stack!==i.stack&&(s=!0,Ms(e),e.stack=i.stack),this._resyncElements(t),(s||n!==e._stacked)&&vs(this,e._parsed)}configure(){const t=this.chart.config,e=t.datasetScopeKeys(this._type),i=t.getOptionScopes(this.getDataset(),e,!0);this.options=t.createResolver(i,this.getContext()),this._parsing=this.options.parsing,this._cachedDataOpts={}}parse(t,e){const{_cachedMeta:i,_data:s}=this,{iScale:n,_stacked:o}=i,a=n.axis;let r,l,h,c=0===t&&e===s.length||i._sorted,d=t>0&&i._parsed[t-1];if(!1===this._parsing)i._parsed=s,i._sorted=!0,h=s;else{h=Y(s[t])?this.parseArrayData(i,s,t,e):U(s[t])?this.parseObjectData(i,s,t,e):this.parsePrimitiveData(i,s,t,e);const n=()=>null===l[a]||d&&l[a]<d[a];for(r=0;r<e;++r)i._parsed[r+t]=l=h[r],c&&(n()&&(c=!1),d=l);i._sorted=c}o&&vs(this,h)}parsePrimitiveData(t,e,i,s){const{iScale:n,vScale:o}=t,a=n.axis,r=o.axis,l=n.getLabels(),h=n===o,c=new Array(s);let d,u,f;for(d=0,u=s;d<u;++d)f=d+i,c[d]={[a]:h||n.parse(l[f],f),[r]:o.parse(e[f],f)};return c}parseArrayData(t,e,i,s){const{xScale:n,yScale:o}=t,a=new Array(s);let r,l,h,c;for(r=0,l=s;r<l;++r)h=r+i,c=e[h],a[r]={x:n.parse(c[0],h),y:o.parse(c[1],h)};return a}parseObjectData(t,e,i,s){const{xScale:n,yScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l=new Array(s);let h,c,d,u;for(h=0,c=s;h<c;++h)d=h+i,u=e[d],l[h]={x:n.parse(lt(u,a),d),y:o.parse(lt(u,r),d)};return l}getParsed(t){return this._cachedMeta._parsed[t]}getDataElement(t){return this._cachedMeta.data[t]}applyStack(t,e,i){const s=this.chart,n=this._cachedMeta,o=e[t.axis];return xs({keys:ms(s,!0),values:e._stacks[t.axis]},o,n.index,{mode:i})}updateRangeFromParsed(t,e,i,s){const n=i[e.axis];let o=null===n?NaN:n;const a=s&&i._stacks[e.axis];s&&a&&(s.values=a,o=xs(s,n,this._cachedMeta.index)),t.min=Math.min(t.min,o),t.max=Math.max(t.max,o)}getMinMax(t,e){const i=this._cachedMeta,s=i._parsed,n=i._sorted&&t===i.iScale,o=s.length,a=this._getOtherScale(t),r=((t,e,i)=>t&&!e.hidden&&e._stacked&&{keys:ms(i,!0),values:null})(e,i,this.chart),l={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY},{min:h,max:c}=function(t){const{min:e,max:i,minDefined:s,maxDefined:n}=t.getUserBounds();return{min:s?e:Number.NEGATIVE_INFINITY,max:n?i:Number.POSITIVE_INFINITY}}(a);let d,u;function f(){u=s[d];const e=u[a.axis];return!X(u[t.axis])||h>e||c<e}for(d=0;d<o&&(f()||(this.updateRangeFromParsed(l,t,u,r),!n));++d);if(n)for(d=o-1;d>=0;--d)if(!f()){this.updateRangeFromParsed(l,t,u,r);break}return l}getAllParsedValues(t){const e=this._cachedMeta._parsed,i=[];let s,n,o;for(s=0,n=e.length;s<n;++s)o=e[s][t.axis],X(o)&&i.push(o);return i}getMaxOverflow(){return!1}getLabelAndValue(t){const e=this._cachedMeta,i=e.iScale,s=e.vScale,n=this.getParsed(t);return{label:i?""+i.getLabelForValue(n[i.axis]):"",value:s?""+s.getLabelForValue(n[s.axis]):""}}_update(t){const e=this._cachedMeta;this.update(t||"default"),e._clip=function(t){let e,i,s,n;return U(t)?(e=t.top,i=t.right,s=t.bottom,n=t.left):e=i=s=n=t,{top:e,right:i,bottom:s,left:n,disabled:!1===t}}(K(this.options.clip,function(t,e,i){if(!1===i)return!1;const s=ps(t,i),n=ps(e,i);return{top:n.end,right:s.end,bottom:n.start,left:s.start}}(e.xScale,e.yScale,this.getMaxOverflow())))}update(t){}draw(){const t=this._ctx,e=this.chart,i=this._cachedMeta,s=i.data||[],n=e.chartArea,o=[],a=this._drawStart||0,r=this._drawCount||s.length-a,l=this.options.drawActiveElementsOnTop;let h;for(i.dataset&&i.dataset.draw(t,n,a,r),h=a;h<a+r;++h){const e=s[h];e.hidden||(e.active&&l?o.push(e):e.draw(t,n))}for(h=0;h<o.length;++h)o[h].draw(t,n)}getStyle(t,e){const i=e?"active":"default";return void 0===t&&this._cachedMeta.dataset?this.resolveDatasetElementOptions(i):this.resolveDataElementOptions(t||0,i)}getContext(t,e,i){const s=this.getDataset();let n;if(t>=0&&t<this._cachedMeta.data.length){const e=this._cachedMeta.data[t];n=e.$context||(e.$context=function(t,e,i){return Ye(t,{active:!1,dataIndex:e,parsed:void 0,raw:void 0,element:i,index:e,mode:"default",type:"data"})}(this.getContext(),t,e)),n.parsed=this.getParsed(t),n.raw=s.data[t],n.index=n.dataIndex=t}else n=this.$context||(this.$context=function(t,e){return Ye(t,{active:!1,dataset:void 0,datasetIndex:e,index:e,mode:"default",type:"dataset"})}(this.chart.getContext(),this.index)),n.dataset=s,n.index=n.datasetIndex=this.index;return n.active=!!e,n.mode=i,n}resolveDatasetElementOptions(t){return this._resolveElementOptions(this.datasetElementType.id,t)}resolveDataElementOptions(t,e){return this._resolveElementOptions(this.dataElementType.id,e,t)}_resolveElementOptions(t,e="default",i){const s="active"===e,n=this._cachedDataOpts,o=t+"-"+e,a=n[o],r=this.enableOptionSharing&&ct(i);if(a)return Ss(a,r);const l=this.chart.config,h=l.datasetElementScopeKeys(this._type,t),c=s?[`${t}Hover`,"hover",t,""]:[t,""],d=l.getOptionScopes(this.getDataset(),h),u=Object.keys(bt.elements[t]),f=l.resolveNamedOptions(d,u,(()=>this.getContext(i,s)),c);return f.$shared&&(f.$shared=r,n[o]=Object.freeze(Ss(f,r))),f}_resolveAnimations(t,e,i){const s=this.chart,n=this._cachedDataOpts,o=`animation-${e}`,a=n[o];if(a)return a;let r;if(!1!==s.options.animation){const s=this.chart.config,n=s.datasetAnimationScopeKeys(this._type,e),o=s.getOptionScopes(this.getDataset(),n);r=s.createResolver(o,this.getContext(t,i,e))}const l=new gs(s,r&&r.animations);return r&&r._cacheable&&(n[o]=Object.freeze(l)),l}getSharedOptions(t){if(t.$shared)return this._sharedOptions||(this._sharedOptions=Object.assign({},t))}includeOptions(t,e){return!e||ks(t)||this.chart._animationsDisabled}updateElement(t,e,i,s){ks(s)?Object.assign(t,i):this._resolveAnimations(e,s).update(t,i)}updateSharedOptions(t,e,i){t&&!ks(e)&&this._resolveAnimations(void 0,e).update(t,i)}_setStyle(t,e,i,s){t.active=s;const n=this.getStyle(e,s);this._resolveAnimations(e,i,s).update(t,{options:!s&&this.getSharedOptions(n)||n})}removeHoverStyle(t,e,i){this._setStyle(t,i,"active",!1)}setHoverStyle(t,e,i){this._setStyle(t,i,"active",!0)}_removeDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!1)}_setDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!0)}_resyncElements(t){const e=this._data,i=this._cachedMeta.data;for(const[t,e,i]of this._syncList)this[t](e,i);this._syncList=[];const s=i.length,n=e.length,o=Math.min(n,s);o&&this.parse(0,o),n>s?this._insertElements(s,n-s,t):n<s&&this._removeElements(n,s-n)}_insertElements(t,e,i=!0){const s=this._cachedMeta,n=s.data,o=t+e;let a;const r=t=>{for(t.length+=e,a=t.length-1;a>=o;a--)t[a]=t[a-e]};for(r(n),a=t;a<o;++a)n[a]=new this.dataElementType;this._parsing&&r(s._parsed),this.parse(t,e),i&&this.updateElements(n,t,e,"reset")}updateElements(t,e,i,s){}_removeElements(t,e){const i=this._cachedMeta;if(this._parsing){const s=i._parsed.splice(t,e);i._stacked&&Ms(i,s)}i.data.splice(t,e)}_sync(t){if(this._parsing)this._syncList.push(t);else{const[e,i,s]=t;this[e](i,s)}this.chart._dataChanges.push([this.index,...t])}_onDataPush(){const t=arguments.length;this._sync(["_insertElements",this.getDataset().data.length-t,t])}_onDataPop(){this._sync(["_removeElements",this._cachedMeta.data.length-1,1])}_onDataShift(){this._sync(["_removeElements",0,1])}_onDataSplice(t,e){e&&this._sync(["_removeElements",t,e]);const i=arguments.length-2;i&&this._sync(["_insertElements",t,i])}_onDataUnshift(){this._sync(["_insertElements",0,arguments.length])}}Ps.defaults={},Ps.prototype.datasetElementType=null,Ps.prototype.dataElementType=null;class Ds{constructor(){this.x=void 0,this.y=void 0,this.active=!1,this.options=void 0,this.$animations=void 0}tooltipPosition(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}hasValue(){return Tt(this.x)&&Tt(this.y)}getProps(t,e){const i=this.$animations;if(!e||!i)return this;const s={};return t.forEach((t=>{s[t]=i[t]&&i[t].active()?i[t]._to:this[t]})),s}}Ds.defaults={},Ds.defaultRoutes=void 0;const Cs={values:t=>Y(t)?t:""+t,numeric(t,e,i){if(0===t)return"0";const s=this.chart.options.locale;let n,o=t;if(i.length>1){const e=Math.max(Math.abs(i[0].value),Math.abs(i[i.length-1].value));(e<1e-4||e>1e15)&&(n="scientific"),o=function(t,e){let i=e.length>3?e[2].value-e[1].value:e[1].value-e[0].value;Math.abs(i)>=1&&t!==Math.floor(t)&&(i=t-Math.floor(t));return i}(t,i)}const a=Dt(Math.abs(o)),r=Math.max(Math.min(-1*Math.floor(a),20),0),l={notation:n,minimumFractionDigits:r,maximumFractionDigits:r};return Object.assign(l,this.options.ticks.format),Ri(t,s,l)},logarithmic(t,e,i){if(0===t)return"0";const s=t/Math.pow(10,Math.floor(Dt(t)));return 1===s||2===s||5===s?Cs.numeric.call(this,t,e,i):""}};var Os={formatters:Cs};function As(t,e){const i=t.options.ticks,s=i.maxTicksLimit||function(t){const e=t.options.offset,i=t._tickSize(),s=t._length/i+(e?0:1),n=t._maxLength/i;return Math.floor(Math.min(s,n))}(t),n=i.major.enabled?function(t){const e=[];let i,s;for(i=0,s=t.length;i<s;i++)t[i].major&&e.push(i);return e}(e):[],o=n.length,a=n[0],r=n[o-1],l=[];if(o>s)return function(t,e,i,s){let n,o=0,a=i[0];for(s=Math.ceil(s),n=0;n<t.length;n++)n===a&&(e.push(t[n]),o++,a=i[o*s])}(e,l,n,o/s),l;const h=function(t,e,i){const s=function(t){const e=t.length;let i,s;if(e<2)return!1;for(s=t[0],i=1;i<e;++i)if(t[i]-t[i-1]!==s)return!1;return s}(t),n=e.length/i;if(!s)return Math.max(n,1);const o=At(s);for(let t=0,e=o.length-1;t<e;t++){const e=o[t];if(e>n)return e}return Math.max(n,1)}(n,e,s);if(o>0){let t,i;const s=o>1?Math.round((r-a)/(o-1)):null;for(Ts(e,l,h,$(s)?0:a-s,a),t=0,i=o-1;t<i;t++)Ts(e,l,h,n[t],n[t+1]);return Ts(e,l,h,r,$(s)?e.length:r+s),l}return Ts(e,l,h),l}function Ts(t,e,i,s,n){const o=K(s,0),a=Math.min(K(n,t.length),t.length);let r,l,h,c=0;for(i=Math.ceil(i),n&&(r=n-s,i=r/Math.floor(r/i)),h=o;h<0;)c++,h=Math.round(o+c*i);for(l=Math.max(o,0);l<a;l++)l===h&&(e.push(t[l]),c++,h=Math.round(o+c*i))}bt.set("scale",{display:!0,offset:!1,reverse:!1,beginAtZero:!1,bounds:"ticks",grace:0,grid:{display:!0,lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickLength:8,tickWidth:(t,e)=>e.lineWidth,tickColor:(t,e)=>e.color,offset:!1,borderDash:[],borderDashOffset:0,borderWidth:1},title:{display:!1,text:"",padding:{top:4,bottom:4}},ticks:{minRotation:0,maxRotation:50,mirror:!1,textStrokeWidth:0,textStrokeColor:"",padding:3,display:!0,autoSkip:!0,autoSkipPadding:3,labelOffset:0,callback:Os.formatters.values,minor:{},major:{},align:"center",crossAlign:"near",showLabelBackdrop:!1,backdropColor:"rgba(255, 255, 255, 0.75)",backdropPadding:2}}),bt.route("scale.ticks","color","","color"),bt.route("scale.grid","color","","borderColor"),bt.route("scale.grid","borderColor","","borderColor"),bt.route("scale.title","color","","color"),bt.describe("scale",{_fallback:!1,_scriptable:t=>!t.startsWith("before")&&!t.startsWith("after")&&"callback"!==t&&"parser"!==t,_indexable:t=>"borderDash"!==t&&"tickBorderDash"!==t}),bt.describe("scales",{_fallback:"scale"}),bt.describe("scale.ticks",{_scriptable:t=>"backdropPadding"!==t&&"callback"!==t,_indexable:t=>"backdropPadding"!==t});const Ls=(t,e,i)=>"top"===e||"left"===e?t[e]+i:t[e]-i;function Rs(t,e){const i=[],s=t.length/e,n=t.length;let o=0;for(;o<n;o+=s)i.push(t[Math.floor(o)]);return i}function Es(t,e,i){const s=t.ticks.length,n=Math.min(e,s-1),o=t._startPixel,a=t._endPixel,r=1e-6;let l,h=t.getPixelForTick(n);if(!(i&&(l=1===s?Math.max(h-o,a-h):0===e?(t.getPixelForTick(1)-h)/2:(h-t.getPixelForTick(n-1))/2,h+=n<e?l:-l,h<o-r||h>a+r)))return h}function Is(t){return t.drawTicks?t.tickLength:0}function zs(t,e){if(!t.display)return 0;const i=He(t.font,e),s=Ne(t.padding);return(Y(t.text)?t.text.length:1)*i.lineHeight+s.height}function Fs(t,e,i){let n=s(t);return(i&&"right"!==e||!i&&"right"===e)&&(n=(t=>"left"===t?"right":"right"===t?"left":t)(n)),n}class Bs extends Ds{constructor(t){super(),this.id=t.id,this.type=t.type,this.options=void 0,this.ctx=t.ctx,this.chart=t.chart,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this._margins={left:0,right:0,top:0,bottom:0},this.maxWidth=void 0,this.maxHeight=void 0,this.paddingTop=void 0,this.paddingBottom=void 0,this.paddingLeft=void 0,this.paddingRight=void 0,this.axis=void 0,this.labelRotation=void 0,this.min=void 0,this.max=void 0,this._range=void 0,this.ticks=[],this._gridLineItems=null,this._labelItems=null,this._labelSizes=null,this._length=0,this._maxLength=0,this._longestTextCache={},this._startPixel=void 0,this._endPixel=void 0,this._reversePixels=!1,this._userMax=void 0,this._userMin=void 0,this._suggestedMax=void 0,this._suggestedMin=void 0,this._ticksLength=0,this._borderValue=0,this._cache={},this._dataLimitsCached=!1,this.$context=void 0}init(t){this.options=t.setContext(this.getContext()),this.axis=t.axis,this._userMin=this.parse(t.min),this._userMax=this.parse(t.max),this._suggestedMin=this.parse(t.suggestedMin),this._suggestedMax=this.parse(t.suggestedMax)}parse(t,e){return t}getUserBounds(){let{_userMin:t,_userMax:e,_suggestedMin:i,_suggestedMax:s}=this;return t=q(t,Number.POSITIVE_INFINITY),e=q(e,Number.NEGATIVE_INFINITY),i=q(i,Number.POSITIVE_INFINITY),s=q(s,Number.NEGATIVE_INFINITY),{min:q(t,i),max:q(e,s),minDefined:X(t),maxDefined:X(e)}}getMinMax(t){let e,{min:i,max:s,minDefined:n,maxDefined:o}=this.getUserBounds();if(n&&o)return{min:i,max:s};const a=this.getMatchingVisibleMetas();for(let r=0,l=a.length;r<l;++r)e=a[r].controller.getMinMax(this,t),n||(i=Math.min(i,e.min)),o||(s=Math.max(s,e.max));return i=o&&i>s?s:i,s=n&&i>s?i:s,{min:q(i,q(s,i)),max:q(s,q(i,s))}}getPadding(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}}getTicks(){return this.ticks}getLabels(){const t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]}beforeLayout(){this._cache={},this._dataLimitsCached=!1}beforeUpdate(){J(this.options.beforeUpdate,[this])}update(t,e,i){const{beginAtZero:s,grace:n,ticks:o}=this.options,a=o.sampleSize;this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this._margins=i=Object.assign({left:0,right:0,top:0,bottom:0},i),this.ticks=null,this._labelSizes=null,this._gridLineItems=null,this._labelItems=null,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this._maxLength=this.isHorizontal()?this.width+i.left+i.right:this.height+i.top+i.bottom,this._dataLimitsCached||(this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this._range=$e(this,n,s),this._dataLimitsCached=!0),this.beforeBuildTicks(),this.ticks=this.buildTicks()||[],this.afterBuildTicks();const r=a<this.ticks.length;this._convertTicksToLabels(r?Rs(this.ticks,a):this.ticks),this.configure(),this.beforeCalculateLabelRotation(),this.calculateLabelRotation(),this.afterCalculateLabelRotation(),o.display&&(o.autoSkip||"auto"===o.source)&&(this.ticks=As(this,this.ticks),this._labelSizes=null),r&&this._convertTicksToLabels(this.ticks),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate()}configure(){let t,e,i=this.options.reverse;this.isHorizontal()?(t=this.left,e=this.right):(t=this.top,e=this.bottom,i=!i),this._startPixel=t,this._endPixel=e,this._reversePixels=i,this._length=e-t,this._alignToPixels=this.options.alignToPixels}afterUpdate(){J(this.options.afterUpdate,[this])}beforeSetDimensions(){J(this.options.beforeSetDimensions,[this])}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0}afterSetDimensions(){J(this.options.afterSetDimensions,[this])}_callHooks(t){this.chart.notifyPlugins(t,this.getContext()),J(this.options[t],[this])}beforeDataLimits(){this._callHooks("beforeDataLimits")}determineDataLimits(){}afterDataLimits(){this._callHooks("afterDataLimits")}beforeBuildTicks(){this._callHooks("beforeBuildTicks")}buildTicks(){return[]}afterBuildTicks(){this._callHooks("afterBuildTicks")}beforeTickToLabelConversion(){J(this.options.beforeTickToLabelConversion,[this])}generateTickLabels(t){const e=this.options.ticks;let i,s,n;for(i=0,s=t.length;i<s;i++)n=t[i],n.label=J(e.callback,[n.value,i,t],this)}afterTickToLabelConversion(){J(this.options.afterTickToLabelConversion,[this])}beforeCalculateLabelRotation(){J(this.options.beforeCalculateLabelRotation,[this])}calculateLabelRotation(){const t=this.options,e=t.ticks,i=this.ticks.length,s=e.minRotation||0,n=e.maxRotation;let o,a,r,l=s;if(!this._isVisible()||!e.display||s>=n||i<=1||!this.isHorizontal())return void(this.labelRotation=s);const h=this._getLabelSizes(),c=h.widest.width,d=h.highest.height,u=jt(this.chart.width-c,0,this.maxWidth);o=t.offset?this.maxWidth/i:u/(i-1),c+6>o&&(o=u/(i-(t.offset?.5:1)),a=this.maxHeight-Is(t.grid)-e.padding-zs(t.title,this.chart.options.font),r=Math.sqrt(c*c+d*d),l=zt(Math.min(Math.asin(jt((h.highest.height+6)/o,-1,1)),Math.asin(jt(a/r,-1,1))-Math.asin(jt(d/r,-1,1)))),l=Math.max(s,Math.min(n,l))),this.labelRotation=l}afterCalculateLabelRotation(){J(this.options.afterCalculateLabelRotation,[this])}beforeFit(){J(this.options.beforeFit,[this])}fit(){const t={width:0,height:0},{chart:e,options:{ticks:i,title:s,grid:n}}=this,o=this._isVisible(),a=this.isHorizontal();if(o){const o=zs(s,e.options.font);if(a?(t.width=this.maxWidth,t.height=Is(n)+o):(t.height=this.maxHeight,t.width=Is(n)+o),i.display&&this.ticks.length){const{first:e,last:s,widest:n,highest:o}=this._getLabelSizes(),r=2*i.padding,l=It(this.labelRotation),h=Math.cos(l),c=Math.sin(l);if(a){const e=i.mirror?0:c*n.width+h*o.height;t.height=Math.min(this.maxHeight,t.height+e+r)}else{const e=i.mirror?0:h*n.width+c*o.height;t.width=Math.min(this.maxWidth,t.width+e+r)}this._calculatePadding(e,s,c,h)}}this._handleMargins(),a?(this.width=this._length=e.width-this._margins.left-this._margins.right,this.height=t.height):(this.width=t.width,this.height=this._length=e.height-this._margins.top-this._margins.bottom)}_calculatePadding(t,e,i,s){const{ticks:{align:n,padding:o},position:a}=this.options,r=0!==this.labelRotation,l="top"!==a&&"x"===this.axis;if(this.isHorizontal()){const a=this.getPixelForTick(0)-this.left,h=this.right-this.getPixelForTick(this.ticks.length-1);let c=0,d=0;r?l?(c=s*t.width,d=i*e.height):(c=i*t.height,d=s*e.width):"start"===n?d=e.width:"end"===n?c=t.width:(c=t.width/2,d=e.width/2),this.paddingLeft=Math.max((c-a+o)*this.width/(this.width-a),0),this.paddingRight=Math.max((d-h+o)*this.width/(this.width-h),0)}else{let i=e.height/2,s=t.height/2;"start"===n?(i=0,s=t.height):"end"===n&&(i=e.height,s=0),this.paddingTop=i+o,this.paddingBottom=s+o}}_handleMargins(){this._margins&&(this._margins.left=Math.max(this.paddingLeft,this._margins.left),this._margins.top=Math.max(this.paddingTop,this._margins.top),this._margins.right=Math.max(this.paddingRight,this._margins.right),this._margins.bottom=Math.max(this.paddingBottom,this._margins.bottom))}afterFit(){J(this.options.afterFit,[this])}isHorizontal(){const{axis:t,position:e}=this.options;return"top"===e||"bottom"===e||"x"===t}isFullSize(){return this.options.fullSize}_convertTicksToLabels(t){let e,i;for(this.beforeTickToLabelConversion(),this.generateTickLabels(t),e=0,i=t.length;e<i;e++)$(t[e].label)&&(t.splice(e,1),i--,e--);this.afterTickToLabelConversion()}_getLabelSizes(){let t=this._labelSizes;if(!t){const e=this.options.ticks.sampleSize;let i=this.ticks;e<i.length&&(i=Rs(i,e)),this._labelSizes=t=this._computeLabelSizes(i,i.length)}return t}_computeLabelSizes(t,e){const{ctx:i,_longestTextCache:s}=this,n=[],o=[];let a,r,l,h,c,d,u,f,g,p,m,x=0,b=0;for(a=0;a<e;++a){if(h=t[a].label,c=this._resolveTickFontOptions(a),i.font=d=c.string,u=s[d]=s[d]||{data:{},gc:[]},f=c.lineHeight,g=p=0,$(h)||Y(h)){if(Y(h))for(r=0,l=h.length;r<l;++r)m=h[r],$(m)||Y(m)||(g=Xt(i,u.data,u.gc,g,m),p+=f)}else g=Xt(i,u.data,u.gc,g,h),p=f;n.push(g),o.push(p),x=Math.max(g,x),b=Math.max(p,b)}!function(t,e){Q(t,(t=>{const i=t.gc,s=i.length/2;let n;if(s>e){for(n=0;n<s;++n)delete t.data[i[n]];i.splice(0,s)}}))}(s,e);const _=n.indexOf(x),y=o.indexOf(b),v=t=>({width:n[t]||0,height:o[t]||0});return{first:v(0),last:v(e-1),widest:v(_),highest:v(y),widths:n,heights:o}}getLabelForValue(t){return t}getPixelForValue(t,e){return NaN}getValueForPixel(t){}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getPixelForDecimal(t){this._reversePixels&&(t=1-t);const e=this._startPixel+t*this._length;return $t(this._alignToPixels?Kt(this.chart,e,0):e)}getDecimalForPixel(t){const e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:e}=this;return t<0&&e<0?e:t>0&&e>0?t:0}getContext(t){const e=this.ticks||[];if(t>=0&&t<e.length){const i=e[t];return i.$context||(i.$context=function(t,e,i){return Ye(t,{tick:i,index:e,type:"tick"})}(this.getContext(),t,i))}return this.$context||(this.$context=Ye(this.chart.getContext(),{scale:this,type:"scale"}))}_tickSize(){const t=this.options.ticks,e=It(this.labelRotation),i=Math.abs(Math.cos(e)),s=Math.abs(Math.sin(e)),n=this._getLabelSizes(),o=t.autoSkipPadding||0,a=n?n.widest.width+o:0,r=n?n.highest.height+o:0;return this.isHorizontal()?r*i>a*s?a/i:r/s:r*s<a*i?r/i:a/s}_isVisible(){const t=this.options.display;return"auto"!==t?!!t:this.getMatchingVisibleMetas().length>0}_computeGridLineItems(t){const e=this.axis,i=this.chart,s=this.options,{grid:n,position:o}=s,a=n.offset,r=this.isHorizontal(),l=this.ticks.length+(a?1:0),h=Is(n),c=[],d=n.setContext(this.getContext()),u=d.drawBorder?d.borderWidth:0,f=u/2,g=function(t){return Kt(i,t,u)};let p,m,x,b,_,y,v,w,M,k,S,P;if("top"===o)p=g(this.bottom),y=this.bottom-h,w=p-f,k=g(t.top)+f,P=t.bottom;else if("bottom"===o)p=g(this.top),k=t.top,P=g(t.bottom)-f,y=p+f,w=this.top+h;else if("left"===o)p=g(this.right),_=this.right-h,v=p-f,M=g(t.left)+f,S=t.right;else if("right"===o)p=g(this.left),M=t.left,S=g(t.right)-f,_=p+f,v=this.left+h;else if("x"===e){if("center"===o)p=g((t.top+t.bottom)/2+.5);else if(U(o)){const t=Object.keys(o)[0],e=o[t];p=g(this.chart.scales[t].getPixelForValue(e))}k=t.top,P=t.bottom,y=p+f,w=y+h}else if("y"===e){if("center"===o)p=g((t.left+t.right)/2);else if(U(o)){const t=Object.keys(o)[0],e=o[t];p=g(this.chart.scales[t].getPixelForValue(e))}_=p-f,v=_-h,M=t.left,S=t.right}const D=K(s.ticks.maxTicksLimit,l),C=Math.max(1,Math.ceil(l/D));for(m=0;m<l;m+=C){const t=n.setContext(this.getContext(m)),e=t.lineWidth,s=t.color,o=n.borderDash||[],l=t.borderDashOffset,h=t.tickWidth,d=t.tickColor,u=t.tickBorderDash||[],f=t.tickBorderDashOffset;x=Es(this,m,a),void 0!==x&&(b=Kt(i,x,e),r?_=v=M=S=b:y=w=k=P=b,c.push({tx1:_,ty1:y,tx2:v,ty2:w,x1:M,y1:k,x2:S,y2:P,width:e,color:s,borderDash:o,borderDashOffset:l,tickWidth:h,tickColor:d,tickBorderDash:u,tickBorderDashOffset:f}))}return this._ticksLength=l,this._borderValue=p,c}_computeLabelItems(t){const e=this.axis,i=this.options,{position:s,ticks:n}=i,o=this.isHorizontal(),a=this.ticks,{align:r,crossAlign:l,padding:h,mirror:c}=n,d=Is(i.grid),u=d+h,f=c?-h:u,g=-It(this.labelRotation),p=[];let m,x,b,_,y,v,w,M,k,S,P,D,C="middle";if("top"===s)v=this.bottom-f,w=this._getXAxisLabelAlignment();else if("bottom"===s)v=this.top+f,w=this._getXAxisLabelAlignment();else if("left"===s){const t=this._getYAxisLabelAlignment(d);w=t.textAlign,y=t.x}else if("right"===s){const t=this._getYAxisLabelAlignment(d);w=t.textAlign,y=t.x}else if("x"===e){if("center"===s)v=(t.top+t.bottom)/2+u;else if(U(s)){const t=Object.keys(s)[0],e=s[t];v=this.chart.scales[t].getPixelForValue(e)+u}w=this._getXAxisLabelAlignment()}else if("y"===e){if("center"===s)y=(t.left+t.right)/2-u;else if(U(s)){const t=Object.keys(s)[0],e=s[t];y=this.chart.scales[t].getPixelForValue(e)}w=this._getYAxisLabelAlignment(d).textAlign}"y"===e&&("start"===r?C="top":"end"===r&&(C="bottom"));const O=this._getLabelSizes();for(m=0,x=a.length;m<x;++m){b=a[m],_=b.label;const t=n.setContext(this.getContext(m));M=this.getPixelForTick(m)+n.labelOffset,k=this._resolveTickFontOptions(m),S=k.lineHeight,P=Y(_)?_.length:1;const e=P/2,i=t.color,r=t.textStrokeColor,h=t.textStrokeWidth;let d;if(o?(y=M,D="top"===s?"near"===l||0!==g?-P*S+S/2:"center"===l?-O.highest.height/2-e*S+S:-O.highest.height+S/2:"near"===l||0!==g?S/2:"center"===l?O.highest.height/2-e*S:O.highest.height-P*S,c&&(D*=-1)):(v=M,D=(1-P)*S/2),t.showLabelBackdrop){const e=Ne(t.backdropPadding),i=O.heights[m],s=O.widths[m];let n=v+D-e.top,o=y-e.left;switch(C){case"middle":n-=i/2;break;case"bottom":n-=i}switch(w){case"center":o-=s/2;break;case"right":o-=s}d={left:o,top:n,width:s+e.width,height:i+e.height,color:t.backdropColor}}p.push({rotation:g,label:_,font:k,color:i,strokeColor:r,strokeWidth:h,textOffset:D,textAlign:w,textBaseline:C,translation:[y,v],backdrop:d})}return p}_getXAxisLabelAlignment(){const{position:t,ticks:e}=this.options;if(-It(this.labelRotation))return"top"===t?"left":"right";let i="center";return"start"===e.align?i="left":"end"===e.align&&(i="right"),i}_getYAxisLabelAlignment(t){const{position:e,ticks:{crossAlign:i,mirror:s,padding:n}}=this.options,o=t+n,a=this._getLabelSizes().widest.width;let r,l;return"left"===e?s?(l=this.right+n,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l+=a)):(l=this.right-o,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l=this.left)):"right"===e?s?(l=this.left+n,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l-=a)):(l=this.left+o,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l=this.right)):r="right",{textAlign:r,x:l}}_computeLabelArea(){if(this.options.ticks.mirror)return;const t=this.chart,e=this.options.position;return"left"===e||"right"===e?{top:0,left:this.left,bottom:t.height,right:this.right}:"top"===e||"bottom"===e?{top:this.top,left:0,bottom:this.bottom,right:t.width}:void 0}drawBackground(){const{ctx:t,options:{backgroundColor:e},left:i,top:s,width:n,height:o}=this;e&&(t.save(),t.fillStyle=e,t.fillRect(i,s,n,o),t.restore())}getLineWidthForValue(t){const e=this.options.grid;if(!this._isVisible()||!e.display)return 0;const i=this.ticks.findIndex((e=>e.value===t));if(i>=0){return e.setContext(this.getContext(i)).lineWidth}return 0}drawGrid(t){const e=this.options.grid,i=this.ctx,s=this._gridLineItems||(this._gridLineItems=this._computeGridLineItems(t));let n,o;const a=(t,e,s)=>{s.width&&s.color&&(i.save(),i.lineWidth=s.width,i.strokeStyle=s.color,i.setLineDash(s.borderDash||[]),i.lineDashOffset=s.borderDashOffset,i.beginPath(),i.moveTo(t.x,t.y),i.lineTo(e.x,e.y),i.stroke(),i.restore())};if(e.display)for(n=0,o=s.length;n<o;++n){const t=s[n];e.drawOnChartArea&&a({x:t.x1,y:t.y1},{x:t.x2,y:t.y2},t),e.drawTicks&&a({x:t.tx1,y:t.ty1},{x:t.tx2,y:t.ty2},{color:t.tickColor,width:t.tickWidth,borderDash:t.tickBorderDash,borderDashOffset:t.tickBorderDashOffset})}}drawBorder(){const{chart:t,ctx:e,options:{grid:i}}=this,s=i.setContext(this.getContext()),n=i.drawBorder?s.borderWidth:0;if(!n)return;const o=i.setContext(this.getContext(0)).lineWidth,a=this._borderValue;let r,l,h,c;this.isHorizontal()?(r=Kt(t,this.left,n)-n/2,l=Kt(t,this.right,o)+o/2,h=c=a):(h=Kt(t,this.top,n)-n/2,c=Kt(t,this.bottom,o)+o/2,r=l=a),e.save(),e.lineWidth=s.borderWidth,e.strokeStyle=s.borderColor,e.beginPath(),e.moveTo(r,h),e.lineTo(l,c),e.stroke(),e.restore()}drawLabels(t){if(!this.options.ticks.display)return;const e=this.ctx,i=this._computeLabelArea();i&&Qt(e,i);const s=this._labelItems||(this._labelItems=this._computeLabelItems(t));let n,o;for(n=0,o=s.length;n<o;++n){const t=s[n],i=t.font,o=t.label;t.backdrop&&(e.fillStyle=t.backdrop.color,e.fillRect(t.backdrop.left,t.backdrop.top,t.backdrop.width,t.backdrop.height)),se(e,o,0,t.textOffset,i,t)}i&&te(e)}drawTitle(){const{ctx:t,options:{position:e,title:i,reverse:s}}=this;if(!i.display)return;const o=He(i.font),a=Ne(i.padding),r=i.align;let l=o.lineHeight/2;"bottom"===e||"center"===e||U(e)?(l+=a.bottom,Y(i.text)&&(l+=o.lineHeight*(i.text.length-1))):l+=a.top;const{titleX:h,titleY:c,maxWidth:d,rotation:u}=function(t,e,i,s){const{top:o,left:a,bottom:r,right:l,chart:h}=t,{chartArea:c,scales:d}=h;let u,f,g,p=0;const m=r-o,x=l-a;if(t.isHorizontal()){if(f=n(s,a,l),U(i)){const t=Object.keys(i)[0],s=i[t];g=d[t].getPixelForValue(s)+m-e}else g="center"===i?(c.bottom+c.top)/2+m-e:Ls(t,i,e);u=l-a}else{if(U(i)){const t=Object.keys(i)[0],s=i[t];f=d[t].getPixelForValue(s)-x+e}else f="center"===i?(c.left+c.right)/2-x+e:Ls(t,i,e);g=n(s,r,o),p="left"===i?-kt:kt}return{titleX:f,titleY:g,maxWidth:u,rotation:p}}(this,l,e,r);se(t,i.text,0,0,o,{color:i.color,maxWidth:d,rotation:u,textAlign:Fs(r,e,s),textBaseline:"middle",translation:[h,c]})}draw(t){this._isVisible()&&(this.drawBackground(),this.drawGrid(t),this.drawBorder(),this.drawTitle(),this.drawLabels(t))}_layers(){const t=this.options,e=t.ticks&&t.ticks.z||0,i=K(t.grid&&t.grid.z,-1);return this._isVisible()&&this.draw===Bs.prototype.draw?[{z:i,draw:t=>{this.drawBackground(),this.drawGrid(t),this.drawTitle()}},{z:i+1,draw:()=>{this.drawBorder()}},{z:e,draw:t=>{this.drawLabels(t)}}]:[{z:e,draw:t=>{this.draw(t)}}]}getMatchingVisibleMetas(t){const e=this.chart.getSortedVisibleDatasetMetas(),i=this.axis+"AxisID",s=[];let n,o;for(n=0,o=e.length;n<o;++n){const o=e[n];o[i]!==this.id||t&&o.type!==t||s.push(o)}return s}_resolveTickFontOptions(t){return He(this.options.ticks.setContext(this.getContext(t)).font)}_maxDigits(){const t=this._resolveTickFontOptions(0).lineHeight;return(this.isHorizontal()?this.width:this.height)/t}}class Vs{constructor(t,e,i){this.type=t,this.scope=e,this.override=i,this.items=Object.create(null)}isForType(t){return Object.prototype.isPrototypeOf.call(this.type.prototype,t.prototype)}register(t){const e=Object.getPrototypeOf(t);let i;(function(t){return"id"in t&&"defaults"in t})(e)&&(i=this.register(e));const s=this.items,n=t.id,o=this.scope+"."+n;if(!n)throw new Error("class does not have id: "+t);return n in s||(s[n]=t,function(t,e,i){const s=nt(Object.create(null),[i?bt.get(i):{},bt.get(e),t.defaults]);bt.set(e,s),t.defaultRoutes&&function(t,e){Object.keys(e).forEach((i=>{const s=i.split("."),n=s.pop(),o=[t].concat(s).join("."),a=e[i].split("."),r=a.pop(),l=a.join(".");bt.route(o,n,l,r)}))}(e,t.defaultRoutes);t.descriptors&&bt.describe(e,t.descriptors)}(t,o,i),this.override&&bt.override(t.id,t.overrides)),o}get(t){return this.items[t]}unregister(t){const e=this.items,i=t.id,s=this.scope;i in e&&delete e[i],s&&i in bt[s]&&(delete bt[s][i],this.override&&delete gt[i])}}var Ws=new class{constructor(){this.controllers=new Vs(Ps,"datasets",!0),this.elements=new Vs(Ds,"elements"),this.plugins=new Vs(Object,"plugins"),this.scales=new Vs(Bs,"scales"),this._typedRegistries=[this.controllers,this.scales,this.elements]}add(...t){this._each("register",t)}remove(...t){this._each("unregister",t)}addControllers(...t){this._each("register",t,this.controllers)}addElements(...t){this._each("register",t,this.elements)}addPlugins(...t){this._each("register",t,this.plugins)}addScales(...t){this._each("register",t,this.scales)}getController(t){return this._get(t,this.controllers,"controller")}getElement(t){return this._get(t,this.elements,"element")}getPlugin(t){return this._get(t,this.plugins,"plugin")}getScale(t){return this._get(t,this.scales,"scale")}removeControllers(...t){this._each("unregister",t,this.controllers)}removeElements(...t){this._each("unregister",t,this.elements)}removePlugins(...t){this._each("unregister",t,this.plugins)}removeScales(...t){this._each("unregister",t,this.scales)}_each(t,e,i){[...e].forEach((e=>{const s=i||this._getRegistryForType(e);i||s.isForType(e)||s===this.plugins&&e.id?this._exec(t,s,e):Q(e,(e=>{const s=i||this._getRegistryForType(e);this._exec(t,s,e)}))}))}_exec(t,e,i){const s=ht(t);J(i["before"+s],[],i),e[t](i),J(i["after"+s],[],i)}_getRegistryForType(t){for(let e=0;e<this._typedRegistries.length;e++){const i=this._typedRegistries[e];if(i.isForType(t))return i}return this.plugins}_get(t,e,i){const s=e.get(t);if(void 0===s)throw new Error('"'+t+'" is not a registered '+i+".");return s}};class Ns{constructor(){this._init=[]}notify(t,e,i,s){"beforeInit"===e&&(this._init=this._createDescriptors(t,!0),this._notify(this._init,t,"install"));const n=s?this._descriptors(t).filter(s):this._descriptors(t),o=this._notify(n,t,e,i);return"afterDestroy"===e&&(this._notify(n,t,"stop"),this._notify(this._init,t,"uninstall")),o}_notify(t,e,i,s){s=s||{};for(const n of t){const t=n.plugin;if(!1===J(t[i],[e,s,n.options],t)&&s.cancelable)return!1}return!0}invalidate(){$(this._cache)||(this._oldCache=this._cache,this._cache=void 0)}_descriptors(t){if(this._cache)return this._cache;const e=this._cache=this._createDescriptors(t);return this._notifyStateChanges(t),e}_createDescriptors(t,e){const i=t&&t.config,s=K(i.options&&i.options.plugins,{}),n=function(t){const e=[],i=Object.keys(Ws.plugins.items);for(let t=0;t<i.length;t++)e.push(Ws.getPlugin(i[t]));const s=t.plugins||[];for(let t=0;t<s.length;t++){const i=s[t];-1===e.indexOf(i)&&e.push(i)}return e}(i);return!1!==s||e?function(t,e,i,s){const n=[],o=t.getContext();for(let a=0;a<e.length;a++){const r=e[a],l=Hs(i[r.id],s);null!==l&&n.push({plugin:r,options:js(t.config,r,l,o)})}return n}(t,n,s,e):[]}_notifyStateChanges(t){const e=this._oldCache||[],i=this._cache,s=(t,e)=>t.filter((t=>!e.some((e=>t.plugin.id===e.plugin.id))));this._notify(s(e,i),t,"stop"),this._notify(s(i,e),t,"start")}}function Hs(t,e){return e||!1!==t?!0===t?{}:t:null}function js(t,e,i,s){const n=t.pluginScopeKeys(e),o=t.getOptionScopes(i,n);return t.createResolver(o,s,[""],{scriptable:!1,indexable:!1,allKeys:!0})}function $s(t,e){const i=bt.datasets[t]||{};return((e.datasets||{})[t]||{}).indexAxis||e.indexAxis||i.indexAxis||"x"}function Ys(t,e){return"x"===t||"y"===t?t:e.axis||("top"===(i=e.position)||"bottom"===i?"x":"left"===i||"right"===i?"y":void 0)||t.charAt(0).toLowerCase();var i}function Us(t){const e=t.options||(t.options={});e.plugins=K(e.plugins,{}),e.scales=function(t,e){const i=gt[t.type]||{scales:{}},s=e.scales||{},n=$s(t.type,e),o=Object.create(null),a=Object.create(null);return Object.keys(s).forEach((t=>{const e=s[t];if(!U(e))return console.error(`Invalid scale configuration for scale: ${t}`);if(e._proxy)return console.warn(`Ignoring resolver passed as options for scale: ${t}`);const r=Ys(t,e),l=function(t,e){return t===e?"_index_":"_value_"}(r,n),h=i.scales||{};o[r]=o[r]||t,a[t]=ot(Object.create(null),[{axis:r},e,h[r],h[l]])})),t.data.datasets.forEach((i=>{const n=i.type||t.type,r=i.indexAxis||$s(n,e),l=(gt[n]||{}).scales||{};Object.keys(l).forEach((t=>{const e=function(t,e){let i=t;return"_index_"===t?i=e:"_value_"===t&&(i="x"===e?"y":"x"),i}(t,r),n=i[e+"AxisID"]||o[e]||e;a[n]=a[n]||Object.create(null),ot(a[n],[{axis:e},s[n],l[t]])}))})),Object.keys(a).forEach((t=>{const e=a[t];ot(e,[bt.scales[e.type],bt.scale])})),a}(t,e)}function Xs(t){return(t=t||{}).datasets=t.datasets||[],t.labels=t.labels||[],t}const qs=new Map,Ks=new Set;function Gs(t,e){let i=qs.get(t);return i||(i=e(),qs.set(t,i),Ks.add(i)),i}const Zs=(t,e,i)=>{const s=lt(e,i);void 0!==s&&t.add(s)};class Js{constructor(t){this._config=function(t){return(t=t||{}).data=Xs(t.data),Us(t),t}(t),this._scopeCache=new Map,this._resolverCache=new Map}get platform(){return this._config.platform}get type(){return this._config.type}set type(t){this._config.type=t}get data(){return this._config.data}set data(t){this._config.data=Xs(t)}get options(){return this._config.options}set options(t){this._config.options=t}get plugins(){return this._config.plugins}update(){const t=this._config;this.clearCache(),Us(t)}clearCache(){this._scopeCache.clear(),this._resolverCache.clear()}datasetScopeKeys(t){return Gs(t,(()=>[[`datasets.${t}`,""]]))}datasetAnimationScopeKeys(t,e){return Gs(`${t}.transition.${e}`,(()=>[[`datasets.${t}.transitions.${e}`,`transitions.${e}`],[`datasets.${t}`,""]]))}datasetElementScopeKeys(t,e){return Gs(`${t}-${e}`,(()=>[[`datasets.${t}.elements.${e}`,`datasets.${t}`,`elements.${e}`,""]]))}pluginScopeKeys(t){const e=t.id;return Gs(`${this.type}-plugin-${e}`,(()=>[[`plugins.${e}`,...t.additionalOptionScopes||[]]]))}_cachedScopes(t,e){const i=this._scopeCache;let s=i.get(t);return s&&!e||(s=new Map,i.set(t,s)),s}getOptionScopes(t,e,i){const{options:s,type:n}=this,o=this._cachedScopes(t,i),a=o.get(e);if(a)return a;const r=new Set;e.forEach((e=>{t&&(r.add(t),e.forEach((e=>Zs(r,t,e)))),e.forEach((t=>Zs(r,s,t))),e.forEach((t=>Zs(r,gt[n]||{},t))),e.forEach((t=>Zs(r,bt,t))),e.forEach((t=>Zs(r,pt,t)))}));const l=Array.from(r);return 0===l.length&&l.push(Object.create(null)),Ks.has(e)&&o.set(e,l),l}chartOptionScopes(){const{options:t,type:e}=this;return[t,gt[e]||{},bt.datasets[e]||{},{type:e},bt,pt]}resolveNamedOptions(t,e,i,s=[""]){const n={$shared:!0},{resolver:o,subPrefixes:a}=Qs(this._resolverCache,t,s);let r=o;if(function(t,e){const{isScriptable:i,isIndexable:s}=ri(t);for(const n of e){const e=i(n),o=s(n),a=(o||e)&&t[n];if(e&&(dt(a)||tn(a))||o&&Y(a))return!0}return!1}(o,e)){n.$shared=!1;r=ai(o,i=dt(i)?i():i,this.createResolver(t,i,a))}for(const t of e)n[t]=r[t];return n}createResolver(t,e,i=[""],s){const{resolver:n}=Qs(this._resolverCache,t,i);return U(e)?ai(n,e,void 0,s):n}}function Qs(t,e,i){let s=t.get(e);s||(s=new Map,t.set(e,s));const n=i.join();let o=s.get(n);if(!o){o={resolver:oi(e,i),subPrefixes:i.filter((t=>!t.toLowerCase().includes("hover")))},s.set(n,o)}return o}const tn=t=>U(t)&&Object.getOwnPropertyNames(t).reduce(((e,i)=>e||dt(t[i])),!1);const en=["top","bottom","left","right","chartArea"];function sn(t,e){return"top"===t||"bottom"===t||-1===en.indexOf(t)&&"x"===e}function nn(t,e){return function(i,s){return i[t]===s[t]?i[e]-s[e]:i[t]-s[t]}}function on(t){const e=t.chart,i=e.options.animation;e.notifyPlugins("afterRender"),J(i&&i.onComplete,[t],e)}function an(t){const e=t.chart,i=e.options.animation;J(i&&i.onProgress,[t],e)}function rn(t){return ge()&&"string"==typeof t?t=document.getElementById(t):t&&t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas),t}const ln={},hn=t=>{const e=rn(t);return Object.values(ln).filter((t=>t.canvas===e)).pop()};function cn(t,e,i){const s=Object.keys(t);for(const n of s){const s=+n;if(s>=e){const o=t[n];delete t[n],(i>0||s>e)&&(t[s+i]=o)}}}class dn{constructor(t,e){const s=this.config=new Js(e),n=rn(t),o=hn(n);if(o)throw new Error("Canvas is already in use. Chart with ID '"+o.id+"' must be destroyed before the canvas can be reused.");const r=s.createResolver(s.chartOptionScopes(),this.getContext());this.platform=new(s.platform||ls(n)),this.platform.updateConfig(s);const l=this.platform.acquireContext(n,r.aspectRatio),h=l&&l.canvas,c=h&&h.height,d=h&&h.width;this.id=j(),this.ctx=l,this.canvas=h,this.width=d,this.height=c,this._options=r,this._aspectRatio=this.aspectRatio,this._layers=[],this._metasets=[],this._stacks=void 0,this.boxes=[],this.currentDevicePixelRatio=void 0,this.chartArea=void 0,this._active=[],this._lastEvent=void 0,this._listeners={},this._responsiveListeners=void 0,this._sortedMetasets=[],this.scales={},this._plugins=new Ns,this.$proxies={},this._hiddenIndices={},this.attached=!1,this._animationsDisabled=void 0,this.$context=void 0,this._doResize=i((t=>this.update(t)),r.resizeDelay||0),this._dataChanges=[],ln[this.id]=this,l&&h?(a.listen(this,"complete",on),a.listen(this,"progress",an),this._initialize(),this.attached&&this.update()):console.error("Failed to create chart: can't acquire context from the given item")}get aspectRatio(){const{options:{aspectRatio:t,maintainAspectRatio:e},width:i,height:s,_aspectRatio:n}=this;return $(t)?e&&n?n:s?i/s:null:t}get data(){return this.config.data}set data(t){this.config.data=t}get options(){return this._options}set options(t){this.config.options=t}_initialize(){return this.notifyPlugins("beforeInit"),this.options.responsive?this.resize():ke(this,this.options.devicePixelRatio),this.bindEvents(),this.notifyPlugins("afterInit"),this}clear(){return Gt(this.canvas,this.ctx),this}stop(){return a.stop(this),this}resize(t,e){a.running(this)?this._resizeBeforeDraw={width:t,height:e}:this._resize(t,e)}_resize(t,e){const i=this.options,s=this.canvas,n=i.maintainAspectRatio&&this.aspectRatio,o=this.platform.getMaximumSize(s,t,e,n),a=i.devicePixelRatio||this.platform.getDevicePixelRatio(),r=this.width?"resize":"attach";this.width=o.width,this.height=o.height,this._aspectRatio=this.aspectRatio,ke(this,a,!0)&&(this.notifyPlugins("resize",{size:o}),J(i.onResize,[this,o],this),this.attached&&this._doResize(r)&&this.render())}ensureScalesHaveIDs(){Q(this.options.scales||{},((t,e)=>{t.id=e}))}buildOrUpdateScales(){const t=this.options,e=t.scales,i=this.scales,s=Object.keys(i).reduce(((t,e)=>(t[e]=!1,t)),{});let n=[];e&&(n=n.concat(Object.keys(e).map((t=>{const i=e[t],s=Ys(t,i),n="r"===s,o="x"===s;return{options:i,dposition:n?"chartArea":o?"bottom":"left",dtype:n?"radialLinear":o?"category":"linear"}})))),Q(n,(e=>{const n=e.options,o=n.id,a=Ys(o,n),r=K(n.type,e.dtype);void 0!==n.position&&sn(n.position,a)===sn(e.dposition)||(n.position=e.dposition),s[o]=!0;let l=null;if(o in i&&i[o].type===r)l=i[o];else{l=new(Ws.getScale(r))({id:o,type:r,ctx:this.ctx,chart:this}),i[l.id]=l}l.init(n,t)})),Q(s,((t,e)=>{t||delete i[e]})),Q(i,(t=>{ni.configure(this,t,t.options),ni.addBox(this,t)}))}_updateMetasets(){const t=this._metasets,e=this.data.datasets.length,i=t.length;if(t.sort(((t,e)=>t.index-e.index)),i>e){for(let t=e;t<i;++t)this._destroyDatasetMeta(t);t.splice(e,i-e)}this._sortedMetasets=t.slice(0).sort(nn("order","index"))}_removeUnreferencedMetasets(){const{_metasets:t,data:{datasets:e}}=this;t.length>e.length&&delete this._stacks,t.forEach(((t,i)=>{0===e.filter((e=>e===t._dataset)).length&&this._destroyDatasetMeta(i)}))}buildOrUpdateControllers(){const t=[],e=this.data.datasets;let i,s;for(this._removeUnreferencedMetasets(),i=0,s=e.length;i<s;i++){const s=e[i];let n=this.getDatasetMeta(i);const o=s.type||this.config.type;if(n.type&&n.type!==o&&(this._destroyDatasetMeta(i),n=this.getDatasetMeta(i)),n.type=o,n.indexAxis=s.indexAxis||$s(o,this.options),n.order=s.order||0,n.index=i,n.label=""+s.label,n.visible=this.isDatasetVisible(i),n.controller)n.controller.updateIndex(i),n.controller.linkScales();else{const e=Ws.getController(o),{datasetElementType:s,dataElementType:a}=bt.datasets[o];Object.assign(e.prototype,{dataElementType:Ws.getElement(a),datasetElementType:s&&Ws.getElement(s)}),n.controller=new e(this,i),t.push(n.controller)}}return this._updateMetasets(),t}_resetElements(){Q(this.data.datasets,((t,e)=>{this.getDatasetMeta(e).controller.reset()}),this)}reset(){this._resetElements(),this.notifyPlugins("reset")}update(t){const e=this.config;e.update();const i=this._options=e.createResolver(e.chartOptionScopes(),this.getContext()),s=this._animationsDisabled=!i.animation;if(this._updateScales(),this._checkEventBindings(),this._updateHiddenIndices(),this._plugins.invalidate(),!1===this.notifyPlugins("beforeUpdate",{mode:t,cancelable:!0}))return;const n=this.buildOrUpdateControllers();this.notifyPlugins("beforeElementsUpdate");let o=0;for(let t=0,e=this.data.datasets.length;t<e;t++){const{controller:e}=this.getDatasetMeta(t),i=!s&&-1===n.indexOf(e);e.buildOrUpdateElements(i),o=Math.max(+e.getMaxOverflow(),o)}o=this._minPadding=i.layout.autoPadding?o:0,this._updateLayout(o),s||Q(n,(t=>{t.reset()})),this._updateDatasets(t),this.notifyPlugins("afterUpdate",{mode:t}),this._layers.sort(nn("z","_idx"));const{_active:a,_lastEvent:r}=this;r?this._eventHandler(r,!0):a.length&&this._updateHoverStyles(a,a,!0),this.render()}_updateScales(){Q(this.scales,(t=>{ni.removeBox(this,t)})),this.ensureScalesHaveIDs(),this.buildOrUpdateScales()}_checkEventBindings(){const t=this.options,e=new Set(Object.keys(this._listeners)),i=new Set(t.events);ut(e,i)&&!!this._responsiveListeners===t.responsive||(this.unbindEvents(),this.bindEvents())}_updateHiddenIndices(){const{_hiddenIndices:t}=this,e=this._getUniformDataChanges()||[];for(const{method:i,start:s,count:n}of e){cn(t,s,"_removeElements"===i?-n:n)}}_getUniformDataChanges(){const t=this._dataChanges;if(!t||!t.length)return;this._dataChanges=[];const e=this.data.datasets.length,i=e=>new Set(t.filter((t=>t[0]===e)).map(((t,e)=>e+","+t.splice(1).join(",")))),s=i(0);for(let t=1;t<e;t++)if(!ut(s,i(t)))return;return Array.from(s).map((t=>t.split(","))).map((t=>({method:t[1],start:+t[2],count:+t[3]})))}_updateLayout(t){if(!1===this.notifyPlugins("beforeLayout",{cancelable:!0}))return;ni.update(this,this.width,this.height,t);const e=this.chartArea,i=e.width<=0||e.height<=0;this._layers=[],Q(this.boxes,(t=>{i&&"chartArea"===t.position||(t.configure&&t.configure(),this._layers.push(...t._layers()))}),this),this._layers.forEach(((t,e)=>{t._idx=e})),this.notifyPlugins("afterLayout")}_updateDatasets(t){if(!1!==this.notifyPlugins("beforeDatasetsUpdate",{mode:t,cancelable:!0})){for(let t=0,e=this.data.datasets.length;t<e;++t)this.getDatasetMeta(t).controller.configure();for(let e=0,i=this.data.datasets.length;e<i;++e)this._updateDataset(e,dt(t)?t({datasetIndex:e}):t);this.notifyPlugins("afterDatasetsUpdate",{mode:t})}}_updateDataset(t,e){const i=this.getDatasetMeta(t),s={meta:i,index:t,mode:e,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetUpdate",s)&&(i.controller._update(e),s.cancelable=!1,this.notifyPlugins("afterDatasetUpdate",s))}render(){!1!==this.notifyPlugins("beforeRender",{cancelable:!0})&&(a.has(this)?this.attached&&!a.running(this)&&a.start(this):(this.draw(),on({chart:this})))}draw(){let t;if(this._resizeBeforeDraw){const{width:t,height:e}=this._resizeBeforeDraw;this._resize(t,e),this._resizeBeforeDraw=null}if(this.clear(),this.width<=0||this.height<=0)return;if(!1===this.notifyPlugins("beforeDraw",{cancelable:!0}))return;const e=this._layers;for(t=0;t<e.length&&e[t].z<=0;++t)e[t].draw(this.chartArea);for(this._drawDatasets();t<e.length;++t)e[t].draw(this.chartArea);this.notifyPlugins("afterDraw")}_getSortedDatasetMetas(t){const e=this._sortedMetasets,i=[];let s,n;for(s=0,n=e.length;s<n;++s){const n=e[s];t&&!n.visible||i.push(n)}return i}getSortedVisibleDatasetMetas(){return this._getSortedDatasetMetas(!0)}_drawDatasets(){if(!1===this.notifyPlugins("beforeDatasetsDraw",{cancelable:!0}))return;const t=this.getSortedVisibleDatasetMetas();for(let e=t.length-1;e>=0;--e)this._drawDataset(t[e]);this.notifyPlugins("afterDatasetsDraw")}_drawDataset(t){const e=this.ctx,i=t._clip,s=!i.disabled,n=this.chartArea,o={meta:t,index:t.index,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetDraw",o)&&(s&&Qt(e,{left:!1===i.left?0:n.left-i.left,right:!1===i.right?this.width:n.right+i.right,top:!1===i.top?0:n.top-i.top,bottom:!1===i.bottom?this.height:n.bottom+i.bottom}),t.controller.draw(),s&&te(e),o.cancelable=!1,this.notifyPlugins("afterDatasetDraw",o))}getElementsAtEventForMode(t,e,i,s){const n=Ee.modes[e];return"function"==typeof n?n(this,t,i,s):[]}getDatasetMeta(t){const e=this.data.datasets[t],i=this._metasets;let s=i.filter((t=>t&&t._dataset===e)).pop();return s||(s={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e&&e.order||0,index:t,_dataset:e,_parsed:[],_sorted:!1},i.push(s)),s}getContext(){return this.$context||(this.$context=Ye(null,{chart:this,type:"chart"}))}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const e=this.data.datasets[t];if(!e)return!1;const i=this.getDatasetMeta(t);return"boolean"==typeof i.hidden?!i.hidden:!e.hidden}setDatasetVisibility(t,e){this.getDatasetMeta(t).hidden=!e}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateVisibility(t,e,i){const s=i?"show":"hide",n=this.getDatasetMeta(t),o=n.controller._resolveAnimations(void 0,s);ct(e)?(n.data[e].hidden=!i,this.update()):(this.setDatasetVisibility(t,i),o.update(n,{visible:i}),this.update((e=>e.datasetIndex===t?s:void 0)))}hide(t,e){this._updateVisibility(t,e,!1)}show(t,e){this._updateVisibility(t,e,!0)}_destroyDatasetMeta(t){const e=this._metasets[t];e&&e.controller&&e.controller._destroy(),delete this._metasets[t]}_stop(){let t,e;for(this.stop(),a.remove(this),t=0,e=this.data.datasets.length;t<e;++t)this._destroyDatasetMeta(t)}destroy(){this.notifyPlugins("beforeDestroy");const{canvas:t,ctx:e}=this;this._stop(),this.config.clearCache(),t&&(this.unbindEvents(),Gt(t,e),this.platform.releaseContext(e),this.canvas=null,this.ctx=null),this.notifyPlugins("destroy"),delete ln[this.id],this.notifyPlugins("afterDestroy")}toBase64Image(...t){return this.canvas.toDataURL(...t)}bindEvents(){this.bindUserEvents(),this.options.responsive?this.bindResponsiveEvents():this.attached=!0}bindUserEvents(){const t=this._listeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(t,e,i)=>{t.offsetX=e,t.offsetY=i,this._eventHandler(t)};Q(this.options.events,(t=>i(t,s)))}bindResponsiveEvents(){this._responsiveListeners||(this._responsiveListeners={});const t=this._responsiveListeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(i,s)=>{t[i]&&(e.removeEventListener(this,i,s),delete t[i])},n=(t,e)=>{this.canvas&&this.resize(t,e)};let o;const a=()=>{s("attach",a),this.attached=!0,this.resize(),i("resize",n),i("detach",o)};o=()=>{this.attached=!1,s("resize",n),this._stop(),this._resize(0,0),i("attach",a)},e.isAttached(this.canvas)?a():o()}unbindEvents(){Q(this._listeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._listeners={},Q(this._responsiveListeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._responsiveListeners=void 0}updateHoverStyle(t,e,i){const s=i?"set":"remove";let n,o,a,r;for("dataset"===e&&(n=this.getDatasetMeta(t[0].datasetIndex),n.controller["_"+s+"DatasetHoverStyle"]()),a=0,r=t.length;a<r;++a){o=t[a];const e=o&&this.getDatasetMeta(o.datasetIndex).controller;e&&e[s+"HoverStyle"](o.element,o.datasetIndex,o.index)}}getActiveElements(){return this._active||[]}setActiveElements(t){const e=this._active||[],i=t.map((({datasetIndex:t,index:e})=>{const i=this.getDatasetMeta(t);if(!i)throw new Error("No dataset found at index "+t);return{datasetIndex:t,element:i.data[e],index:e}}));!tt(i,e)&&(this._active=i,this._lastEvent=null,this._updateHoverStyles(i,e))}notifyPlugins(t,e,i){return this._plugins.notify(this,t,e,i)}_updateHoverStyles(t,e,i){const s=this.options.hover,n=(t,e)=>t.filter((t=>!e.some((e=>t.datasetIndex===e.datasetIndex&&t.index===e.index)))),o=n(e,t),a=i?t:n(t,e);o.length&&this.updateHoverStyle(o,s.mode,!1),a.length&&s.mode&&this.updateHoverStyle(a,s.mode,!0)}_eventHandler(t,e){const i={event:t,replay:e,cancelable:!0,inChartArea:Jt(t,this.chartArea,this._minPadding)},s=e=>(e.options.events||this.options.events).includes(t.native.type);if(!1===this.notifyPlugins("beforeEvent",i,s))return;const n=this._handleEvent(t,e,i.inChartArea);return i.cancelable=!1,this.notifyPlugins("afterEvent",i,s),(n||i.changed)&&this.render(),this}_handleEvent(t,e,i){const{_active:s=[],options:n}=this,o=e,a=this._getActiveElements(t,s,i,o),r=ft(t),l=function(t,e,i,s){return i&&"mouseout"!==t.type?s?e:t:null}(t,this._lastEvent,i,r);i&&(this._lastEvent=null,J(n.onHover,[t,a,this],this),r&&J(n.onClick,[t,a,this],this));const h=!tt(a,s);return(h||e)&&(this._active=a,this._updateHoverStyles(a,s,e)),this._lastEvent=l,h}_getActiveElements(t,e,i,s){if("mouseout"===t.type)return[];if(!i)return e;const n=this.options.hover;return this.getElementsAtEventForMode(t,n.mode,n,s)}}const un=()=>Q(dn.instances,(t=>t._plugins.invalidate())),fn=!0;function gn(){throw new Error("This method is not implemented: Check that a complete date adapter is provided.")}Object.defineProperties(dn,{defaults:{enumerable:fn,value:bt},instances:{enumerable:fn,value:ln},overrides:{enumerable:fn,value:gt},registry:{enumerable:fn,value:Ws},version:{enumerable:fn,value:"3.7.0"},getChart:{enumerable:fn,value:hn},register:{enumerable:fn,value:(...t)=>{Ws.add(...t),un()}},unregister:{enumerable:fn,value:(...t)=>{Ws.remove(...t),un()}}});class pn{constructor(t){this.options=t||{}}formats(){return gn()}parse(t,e){return gn()}format(t,e){return gn()}add(t,e,i){return gn()}diff(t,e,i){return gn()}startOf(t,e,i){return gn()}endOf(t,e){return gn()}}pn.override=function(t){Object.assign(pn.prototype,t)};var mn={_date:pn};function xn(t){const e=t.iScale,i=function(t,e){if(!t._cache.$bar){const i=t.getMatchingVisibleMetas(e);let s=[];for(let e=0,n=i.length;e<n;e++)s=s.concat(i[e].controller.getAllParsedValues(t));t._cache.$bar=fe(s.sort(((t,e)=>t-e)))}return t._cache.$bar}(e,t.type);let s,n,o,a,r=e._length;const l=()=>{32767!==o&&-32768!==o&&(ct(a)&&(r=Math.min(r,Math.abs(o-a)||r)),a=o)};for(s=0,n=i.length;s<n;++s)o=e.getPixelForValue(i[s]),l();for(a=void 0,s=0,n=e.ticks.length;s<n;++s)o=e.getPixelForTick(s),l();return r}function bn(t,e,i,s){return Y(t)?function(t,e,i,s){const n=i.parse(t[0],s),o=i.parse(t[1],s),a=Math.min(n,o),r=Math.max(n,o);let l=a,h=r;Math.abs(a)>Math.abs(r)&&(l=r,h=a),e[i.axis]=h,e._custom={barStart:l,barEnd:h,start:n,end:o,min:a,max:r}}(t,e,i,s):e[i.axis]=i.parse(t,s),e}function _n(t,e,i,s){const n=t.iScale,o=t.vScale,a=n.getLabels(),r=n===o,l=[];let h,c,d,u;for(h=i,c=i+s;h<c;++h)u=e[h],d={},d[n.axis]=r||n.parse(a[h],h),l.push(bn(u,d,o,h));return l}function yn(t){return t&&void 0!==t.barStart&&void 0!==t.barEnd}function vn(t,e,i,s){let n=e.borderSkipped;const o={};if(!n)return void(t.borderSkipped=o);const{start:a,end:r,reverse:l,top:h,bottom:c}=function(t){let e,i,s,n,o;return t.horizontal?(e=t.base>t.x,i="left",s="right"):(e=t.base<t.y,i="bottom",s="top"),e?(n="end",o="start"):(n="start",o="end"),{start:i,end:s,reverse:e,top:n,bottom:o}}(t);"middle"===n&&i&&(t.enableBorderRadius=!0,(i._top||0)===s?n=h:(i._bottom||0)===s?n=c:(o[wn(c,a,r,l)]=!0,n=h)),o[wn(n,a,r,l)]=!0,t.borderSkipped=o}function wn(t,e,i,s){var n,o,a;return s?(a=i,t=Mn(t=(n=t)===(o=e)?a:n===a?o:n,i,e)):t=Mn(t,e,i),t}function Mn(t,e,i){return"start"===t?e:"end"===t?i:t}function kn(t,{inflateAmount:e},i){t.inflateAmount="auto"===e?1===i?.33:0:e}class Sn extends Ps{parsePrimitiveData(t,e,i,s){return _n(t,e,i,s)}parseArrayData(t,e,i,s){return _n(t,e,i,s)}parseObjectData(t,e,i,s){const{iScale:n,vScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l="x"===n.axis?a:r,h="x"===o.axis?a:r,c=[];let d,u,f,g;for(d=i,u=i+s;d<u;++d)g=e[d],f={},f[n.axis]=n.parse(lt(g,l),d),c.push(bn(lt(g,h),f,o,d));return c}updateRangeFromParsed(t,e,i,s){super.updateRangeFromParsed(t,e,i,s);const n=i._custom;n&&e===this._cachedMeta.vScale&&(t.min=Math.min(t.min,n.min),t.max=Math.max(t.max,n.max))}getMaxOverflow(){return 0}getLabelAndValue(t){const e=this._cachedMeta,{iScale:i,vScale:s}=e,n=this.getParsed(t),o=n._custom,a=yn(o)?"["+o.start+", "+o.end+"]":""+s.getLabelForValue(n[s.axis]);return{label:""+i.getLabelForValue(n[i.axis]),value:a}}initialize(){this.enableOptionSharing=!0,super.initialize();this._cachedMeta.stack=this.getDataset().stack}update(t){const e=this._cachedMeta;this.updateElements(e.data,0,e.data.length,t)}updateElements(t,e,i,s){const n="reset"===s,{index:o,_cachedMeta:{vScale:a}}=this,r=a.getBasePixel(),l=a.isHorizontal(),h=this._getRuler(),c=this.resolveDataElementOptions(e,s),d=this.getSharedOptions(c),u=this.includeOptions(s,d);this.updateSharedOptions(d,s,c);for(let c=e;c<e+i;c++){const e=this.getParsed(c),i=n||$(e[a.axis])?{base:r,head:r}:this._calculateBarValuePixels(c),f=this._calculateBarIndexPixels(c,h),g=(e._stacks||{})[a.axis],p={horizontal:l,base:i.base,enableBorderRadius:!g||yn(e._custom)||o===g._top||o===g._bottom,x:l?i.head:f.center,y:l?f.center:i.head,height:l?f.size:Math.abs(i.size),width:l?Math.abs(i.size):f.size};u&&(p.options=d||this.resolveDataElementOptions(c,t[c].active?"active":s));const m=p.options||t[c].options;vn(p,m,g,o),kn(p,m,h.ratio),this.updateElement(t[c],c,p,s)}}_getStacks(t,e){const i=this._cachedMeta.iScale,s=i.getMatchingVisibleMetas(this._type),n=i.options.stacked,o=s.length,a=[];let r,l;for(r=0;r<o;++r)if(l=s[r],l.controller.options.grouped){if(void 0!==e){const t=l.controller.getParsed(e)[l.controller._cachedMeta.vScale.axis];if($(t)||isNaN(t))continue}if((!1===n||-1===a.indexOf(l.stack)||void 0===n&&void 0===l.stack)&&a.push(l.stack),l.index===t)break}return a.length||a.push(void 0),a}_getStackCount(t){return this._getStacks(void 0,t).length}_getStackIndex(t,e,i){const s=this._getStacks(t,i),n=void 0!==e?s.indexOf(e):-1;return-1===n?s.length-1:n}_getRuler(){const t=this.options,e=this._cachedMeta,i=e.iScale,s=[];let n,o;for(n=0,o=e.data.length;n<o;++n)s.push(i.getPixelForValue(this.getParsed(n)[i.axis],n));const a=t.barThickness;return{min:a||xn(e),pixels:s,start:i._startPixel,end:i._endPixel,stackCount:this._getStackCount(),scale:i,grouped:t.grouped,ratio:a?1:t.categoryPercentage*t.barPercentage}}_calculateBarValuePixels(t){const{_cachedMeta:{vScale:e,_stacked:i},options:{base:s,minBarLength:n}}=this,o=s||0,a=this.getParsed(t),r=a._custom,l=yn(r);let h,c,d=a[e.axis],u=0,f=i?this.applyStack(e,a,i):d;f!==d&&(u=f-d,f=d),l&&(d=r.barStart,f=r.barEnd-r.barStart,0!==d&&Ct(d)!==Ct(r.barEnd)&&(u=0),u+=d);const g=$(s)||l?u:s;let p=e.getPixelForValue(g);if(h=this.chart.getDataVisibility(t)?e.getPixelForValue(u+f):p,c=h-p,Math.abs(c)<n&&(c=function(t,e,i){return 0!==t?Ct(t):(e.isHorizontal()?1:-1)*(e.min>=i?1:-1)}(c,e,o)*n,d===o&&(p-=c/2),h=p+c),p===e.getPixelForValue(o)){const t=Ct(c)*e.getLineWidthForValue(o)/2;p+=t,c-=t}return{size:c,base:p,head:h,center:h+c/2}}_calculateBarIndexPixels(t,e){const i=e.scale,s=this.options,n=s.skipNull,o=K(s.maxBarThickness,1/0);let a,r;if(e.grouped){const i=n?this._getStackCount(t):e.stackCount,l="flex"===s.barThickness?function(t,e,i,s){const n=e.pixels,o=n[t];let a=t>0?n[t-1]:null,r=t<n.length-1?n[t+1]:null;const l=i.categoryPercentage;null===a&&(a=o-(null===r?e.end-e.start:r-o)),null===r&&(r=o+o-a);const h=o-(o-Math.min(a,r))/2*l;return{chunk:Math.abs(r-a)/2*l/s,ratio:i.barPercentage,start:h}}(t,e,s,i):function(t,e,i,s){const n=i.barThickness;let o,a;return $(n)?(o=e.min*i.categoryPercentage,a=i.barPercentage):(o=n*s,a=1),{chunk:o/s,ratio:a,start:e.pixels[t]-o/2}}(t,e,s,i),h=this._getStackIndex(this.index,this._cachedMeta.stack,n?t:void 0);a=l.start+l.chunk*h+l.chunk/2,r=Math.min(o,l.chunk*l.ratio)}else a=i.getPixelForValue(this.getParsed(t)[i.axis],t),r=Math.min(o,e.min*e.ratio);return{base:a-r/2,head:a+r/2,center:a,size:r}}draw(){const t=this._cachedMeta,e=t.vScale,i=t.data,s=i.length;let n=0;for(;n<s;++n)null!==this.getParsed(n)[e.axis]&&i[n].draw(this._ctx)}}Sn.id="bar",Sn.defaults={datasetElementType:!1,dataElementType:"bar",categoryPercentage:.8,barPercentage:.9,grouped:!0,animations:{numbers:{type:"number",properties:["x","y","base","width","height"]}}},Sn.overrides={scales:{_index_:{type:"category",offset:!0,grid:{offset:!0}},_value_:{type:"linear",beginAtZero:!0}}};class Pn extends Ps{initialize(){this.enableOptionSharing=!0,super.initialize()}parsePrimitiveData(t,e,i,s){const n=super.parsePrimitiveData(t,e,i,s);for(let t=0;t<n.length;t++)n[t]._custom=this.resolveDataElementOptions(t+i).radius;return n}parseArrayData(t,e,i,s){const n=super.parseArrayData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=K(s[2],this.resolveDataElementOptions(t+i).radius)}return n}parseObjectData(t,e,i,s){const n=super.parseObjectData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=K(s&&s.r&&+s.r,this.resolveDataElementOptions(t+i).radius)}return n}getMaxOverflow(){const t=this._cachedMeta.data;let e=0;for(let i=t.length-1;i>=0;--i)e=Math.max(e,t[i].size(this.resolveDataElementOptions(i))/2);return e>0&&e}getLabelAndValue(t){const e=this._cachedMeta,{xScale:i,yScale:s}=e,n=this.getParsed(t),o=i.getLabelForValue(n.x),a=s.getLabelForValue(n.y),r=n._custom;return{label:e.label,value:"("+o+", "+a+(r?", "+r:"")+")"}}update(t){const e=this._cachedMeta.data;this.updateElements(e,0,e.length,t)}updateElements(t,e,i,s){const n="reset"===s,{iScale:o,vScale:a}=this._cachedMeta,r=this.resolveDataElementOptions(e,s),l=this.getSharedOptions(r),h=this.includeOptions(s,l),c=o.axis,d=a.axis;for(let r=e;r<e+i;r++){const e=t[r],i=!n&&this.getParsed(r),l={},u=l[c]=n?o.getPixelForDecimal(.5):o.getPixelForValue(i[c]),f=l[d]=n?a.getBasePixel():a.getPixelForValue(i[d]);l.skip=isNaN(u)||isNaN(f),h&&(l.options=this.resolveDataElementOptions(r,e.active?"active":s),n&&(l.options.radius=0)),this.updateElement(e,r,l,s)}this.updateSharedOptions(l,s,r)}resolveDataElementOptions(t,e){const i=this.getParsed(t);let s=super.resolveDataElementOptions(t,e);s.$shared&&(s=Object.assign({},s,{$shared:!1}));const n=s.radius;return"active"!==e&&(s.radius=0),s.radius+=K(i&&i._custom,n),s}}Pn.id="bubble",Pn.defaults={datasetElementType:!1,dataElementType:"point",animations:{numbers:{type:"number",properties:["x","y","borderWidth","radius"]}}},Pn.overrides={scales:{x:{type:"linear"},y:{type:"linear"}},plugins:{tooltip:{callbacks:{title:()=>""}}}};class Dn extends Ps{constructor(t,e){super(t,e),this.enableOptionSharing=!0,this.innerRadius=void 0,this.outerRadius=void 0,this.offsetX=void 0,this.offsetY=void 0}linkScales(){}parse(t,e){const i=this.getDataset().data,s=this._cachedMeta;if(!1===this._parsing)s._parsed=i;else{let n,o,a=t=>+i[t];if(U(i[t])){const{key:t="value"}=this._parsing;a=e=>+lt(i[e],t)}for(n=t,o=t+e;n<o;++n)s._parsed[n]=a(n)}}_getRotation(){return It(this.options.rotation-90)}_getCircumference(){return It(this.options.circumference)}_getRotationExtents(){let t=yt,e=-yt;for(let i=0;i<this.chart.data.datasets.length;++i)if(this.chart.isDatasetVisible(i)){const s=this.chart.getDatasetMeta(i).controller,n=s._getRotation(),o=s._getCircumference();t=Math.min(t,n),e=Math.max(e,n+o)}return{rotation:t,circumference:e-t}}update(t){const e=this.chart,{chartArea:i}=e,s=this._cachedMeta,n=s.data,o=this.getMaxBorderWidth()+this.getMaxOffset(n)+this.options.spacing,a=Math.max((Math.min(i.width,i.height)-o)/2,0),r=Math.min(G(this.options.cutout,a),1),l=this._getRingWeight(this.index),{circumference:h,rotation:c}=this._getRotationExtents(),{ratioX:d,ratioY:u,offsetX:f,offsetY:g}=function(t,e,i){let s=1,n=1,o=0,a=0;if(e<yt){const r=t,l=r+e,h=Math.cos(r),c=Math.sin(r),d=Math.cos(l),u=Math.sin(l),f=(t,e,s)=>Ht(t,r,l,!0)?1:Math.max(e,e*i,s,s*i),g=(t,e,s)=>Ht(t,r,l,!0)?-1:Math.min(e,e*i,s,s*i),p=f(0,h,d),m=f(kt,c,u),x=g(_t,h,d),b=g(_t+kt,c,u);s=(p-x)/2,n=(m-b)/2,o=-(p+x)/2,a=-(m+b)/2}return{ratioX:s,ratioY:n,offsetX:o,offsetY:a}}(c,h,r),p=(i.width-o)/d,m=(i.height-o)/u,x=Math.max(Math.min(p,m)/2,0),b=Z(this.options.radius,x),_=(b-Math.max(b*r,0))/this._getVisibleDatasetWeightTotal();this.offsetX=f*b,this.offsetY=g*b,s.total=this.calculateTotal(),this.outerRadius=b-_*this._getRingWeightOffset(this.index),this.innerRadius=Math.max(this.outerRadius-_*l,0),this.updateElements(n,0,n.length,t)}_circumference(t,e){const i=this.options,s=this._cachedMeta,n=this._getCircumference();return e&&i.animation.animateRotate||!this.chart.getDataVisibility(t)||null===s._parsed[t]||s.data[t].hidden?0:this.calculateCircumference(s._parsed[t]*n/yt)}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=o.chartArea,r=o.options.animation,l=(a.left+a.right)/2,h=(a.top+a.bottom)/2,c=n&&r.animateScale,d=c?0:this.innerRadius,u=c?0:this.outerRadius,f=this.resolveDataElementOptions(e,s),g=this.getSharedOptions(f),p=this.includeOptions(s,g);let m,x=this._getRotation();for(m=0;m<e;++m)x+=this._circumference(m,n);for(m=e;m<e+i;++m){const e=this._circumference(m,n),i=t[m],o={x:l+this.offsetX,y:h+this.offsetY,startAngle:x,endAngle:x+e,circumference:e,outerRadius:u,innerRadius:d};p&&(o.options=g||this.resolveDataElementOptions(m,i.active?"active":s)),x+=e,this.updateElement(i,m,o,s)}this.updateSharedOptions(g,s,f)}calculateTotal(){const t=this._cachedMeta,e=t.data;let i,s=0;for(i=0;i<e.length;i++){const n=t._parsed[i];null===n||isNaN(n)||!this.chart.getDataVisibility(i)||e[i].hidden||(s+=Math.abs(n))}return s}calculateCircumference(t){const e=this._cachedMeta.total;return e>0&&!isNaN(t)?yt*(Math.abs(t)/e):0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=Ri(e._parsed[t],i.options.locale);return{label:s[t]||"",value:n}}getMaxBorderWidth(t){let e=0;const i=this.chart;let s,n,o,a,r;if(!t)for(s=0,n=i.data.datasets.length;s<n;++s)if(i.isDatasetVisible(s)){o=i.getDatasetMeta(s),t=o.data,a=o.controller;break}if(!t)return 0;for(s=0,n=t.length;s<n;++s)r=a.resolveDataElementOptions(s),"inner"!==r.borderAlign&&(e=Math.max(e,r.borderWidth||0,r.hoverBorderWidth||0));return e}getMaxOffset(t){let e=0;for(let i=0,s=t.length;i<s;++i){const t=this.resolveDataElementOptions(i);e=Math.max(e,t.offset||0,t.hoverOffset||0)}return e}_getRingWeightOffset(t){let e=0;for(let i=0;i<t;++i)this.chart.isDatasetVisible(i)&&(e+=this._getRingWeight(i));return e}_getRingWeight(t){return Math.max(K(this.chart.data.datasets[t].weight,1),0)}_getVisibleDatasetWeightTotal(){return this._getRingWeightOffset(this.chart.data.datasets.length)||1}}Dn.id="doughnut",Dn.defaults={datasetElementType:!1,dataElementType:"arc",animation:{animateRotate:!0,animateScale:!1},animations:{numbers:{type:"number",properties:["circumference","endAngle","innerRadius","outerRadius","startAngle","x","y","offset","borderWidth","spacing"]}},cutout:"50%",rotation:0,circumference:360,radius:"100%",spacing:0,indexAxis:"r"},Dn.descriptors={_scriptable:t=>"spacing"!==t,_indexable:t=>"spacing"!==t},Dn.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label(t){let e=t.label;const i=": "+t.formattedValue;return Y(e)?(e=e.slice(),e[0]+=i):e+=i,e}}}}};class Cn extends Ps{initialize(){this.enableOptionSharing=!0,super.initialize()}update(t){const e=this._cachedMeta,{dataset:i,data:s=[],_dataset:n}=e,o=this.chart._animationsDisabled;let{start:a,count:r}=function(t,e,i){const s=e.length;let n=0,o=s;if(t._sorted){const{iScale:a,_parsed:r}=t,l=a.axis,{min:h,max:c,minDefined:d,maxDefined:u}=a.getUserBounds();d&&(n=jt(Math.min(re(r,a.axis,h).lo,i?s:re(e,l,a.getPixelForValue(h)).lo),0,s-1)),o=u?jt(Math.max(re(r,a.axis,c).hi+1,i?0:re(e,l,a.getPixelForValue(c)).hi+1),n,s)-n:s-n}return{start:n,count:o}}(e,s,o);this._drawStart=a,this._drawCount=r,function(t){const{xScale:e,yScale:i,_scaleRanges:s}=t,n={xmin:e.min,xmax:e.max,ymin:i.min,ymax:i.max};if(!s)return t._scaleRanges=n,!0;const o=s.xmin!==e.min||s.xmax!==e.max||s.ymin!==i.min||s.ymax!==i.max;return Object.assign(s,n),o}(e)&&(a=0,r=s.length),i._chart=this.chart,i._datasetIndex=this.index,i._decimated=!!n._decimated,i.points=s;const l=this.resolveDatasetElementOptions(t);this.options.showLine||(l.borderWidth=0),l.segment=this.options.segment,this.updateElement(i,void 0,{animated:!o,options:l},t),this.updateElements(s,a,r,t)}updateElements(t,e,i,s){const n="reset"===s,{iScale:o,vScale:a,_stacked:r,_dataset:l}=this._cachedMeta,h=this.resolveDataElementOptions(e,s),c=this.getSharedOptions(h),d=this.includeOptions(s,c),u=o.axis,f=a.axis,{spanGaps:g,segment:p}=this.options,m=Tt(g)?g:Number.POSITIVE_INFINITY,x=this.chart._animationsDisabled||n||"none"===s;let b=e>0&&this.getParsed(e-1);for(let h=e;h<e+i;++h){const e=t[h],i=this.getParsed(h),g=x?e:{},_=$(i[f]),y=g[u]=o.getPixelForValue(i[u],h),v=g[f]=n||_?a.getBasePixel():a.getPixelForValue(r?this.applyStack(a,i,r):i[f],h);g.skip=isNaN(y)||isNaN(v)||_,g.stop=h>0&&i[u]-b[u]>m,p&&(g.parsed=i,g.raw=l.data[h]),d&&(g.options=c||this.resolveDataElementOptions(h,e.active?"active":s)),x||this.updateElement(e,h,g,s),b=i}this.updateSharedOptions(c,s,h)}getMaxOverflow(){const t=this._cachedMeta,e=t.dataset,i=e.options&&e.options.borderWidth||0,s=t.data||[];if(!s.length)return i;const n=s[0].size(this.resolveDataElementOptions(0)),o=s[s.length-1].size(this.resolveDataElementOptions(s.length-1));return Math.max(i,n,o)/2}draw(){const t=this._cachedMeta;t.dataset.updateControlPoints(this.chart.chartArea,t.iScale.axis),super.draw()}}Cn.id="line",Cn.defaults={datasetElementType:"line",dataElementType:"point",showLine:!0,spanGaps:!1},Cn.overrides={scales:{_index_:{type:"category"},_value_:{type:"linear"}}};class On extends Ps{constructor(t,e){super(t,e),this.innerRadius=void 0,this.outerRadius=void 0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=Ri(e._parsed[t].r,i.options.locale);return{label:s[t]||"",value:n}}update(t){const e=this._cachedMeta.data;this._updateRadius(),this.updateElements(e,0,e.length,t)}_updateRadius(){const t=this.chart,e=t.chartArea,i=t.options,s=Math.min(e.right-e.left,e.bottom-e.top),n=Math.max(s/2,0),o=(n-Math.max(i.cutoutPercentage?n/100*i.cutoutPercentage:1,0))/t.getVisibleDatasetCount();this.outerRadius=n-o*this.index,this.innerRadius=this.outerRadius-o}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=this.getDataset(),r=o.options.animation,l=this._cachedMeta.rScale,h=l.xCenter,c=l.yCenter,d=l.getIndexAngle(0)-.5*_t;let u,f=d;const g=360/this.countVisibleElements();for(u=0;u<e;++u)f+=this._computeAngle(u,s,g);for(u=e;u<e+i;u++){const e=t[u];let i=f,p=f+this._computeAngle(u,s,g),m=o.getDataVisibility(u)?l.getDistanceFromCenterForValue(a.data[u]):0;f=p,n&&(r.animateScale&&(m=0),r.animateRotate&&(i=p=d));const x={x:h,y:c,innerRadius:0,outerRadius:m,startAngle:i,endAngle:p,options:this.resolveDataElementOptions(u,e.active?"active":s)};this.updateElement(e,u,x,s)}}countVisibleElements(){const t=this.getDataset(),e=this._cachedMeta;let i=0;return e.data.forEach(((e,s)=>{!isNaN(t.data[s])&&this.chart.getDataVisibility(s)&&i++})),i}_computeAngle(t,e,i){return this.chart.getDataVisibility(t)?It(this.resolveDataElementOptions(t,e).angle||i):0}}On.id="polarArea",On.defaults={dataElementType:"arc",animation:{animateRotate:!0,animateScale:!0},animations:{numbers:{type:"number",properties:["x","y","startAngle","endAngle","innerRadius","outerRadius"]}},indexAxis:"r",startAngle:0},On.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label:t=>t.chart.data.labels[t.dataIndex]+": "+t.formattedValue}}},scales:{r:{type:"radialLinear",angleLines:{display:!1},beginAtZero:!0,grid:{circular:!0},pointLabels:{display:!1},startAngle:0}}};class An extends Dn{}An.id="pie",An.defaults={cutout:0,rotation:0,circumference:360,radius:"100%"};class Tn extends Ps{getLabelAndValue(t){const e=this._cachedMeta.vScale,i=this.getParsed(t);return{label:e.getLabels()[t],value:""+e.getLabelForValue(i[e.axis])}}update(t){const e=this._cachedMeta,i=e.dataset,s=e.data||[],n=e.iScale.getLabels();if(i.points=s,"resize"!==t){const e=this.resolveDatasetElementOptions(t);this.options.showLine||(e.borderWidth=0);const o={_loop:!0,_fullLoop:n.length===s.length,options:e};this.updateElement(i,void 0,o,t)}this.updateElements(s,0,s.length,t)}updateElements(t,e,i,s){const n=this.getDataset(),o=this._cachedMeta.rScale,a="reset"===s;for(let r=e;r<e+i;r++){const e=t[r],i=this.resolveDataElementOptions(r,e.active?"active":s),l=o.getPointPositionForValue(r,n.data[r]),h=a?o.xCenter:l.x,c=a?o.yCenter:l.y,d={x:h,y:c,angle:l.angle,skip:isNaN(h)||isNaN(c),options:i};this.updateElement(e,r,d,s)}}}Tn.id="radar",Tn.defaults={datasetElementType:"line",dataElementType:"point",indexAxis:"r",showLine:!0,elements:{line:{fill:"start"}}},Tn.overrides={aspectRatio:1,scales:{r:{type:"radialLinear"}}};class Ln extends Cn{}Ln.id="scatter",Ln.defaults={showLine:!1,fill:!1},Ln.overrides={interaction:{mode:"point"},plugins:{tooltip:{callbacks:{title:()=>"",label:t=>"("+t.label+", "+t.formattedValue+")"}}},scales:{x:{type:"linear"},y:{type:"linear"}}};var Rn=Object.freeze({__proto__:null,BarController:Sn,BubbleController:Pn,DoughnutController:Dn,LineController:Cn,PolarAreaController:On,PieController:An,RadarController:Tn,ScatterController:Ln});function En(t,e,i){const{startAngle:s,pixelMargin:n,x:o,y:a,outerRadius:r,innerRadius:l}=e;let h=n/r;t.beginPath(),t.arc(o,a,r,s-h,i+h),l>n?(h=n/l,t.arc(o,a,l,i+h,s-h,!0)):t.arc(o,a,n,i+kt,s-kt),t.closePath(),t.clip()}function In(t,e,i,s){const n=Be(t.options.borderRadius,["outerStart","outerEnd","innerStart","innerEnd"]);const o=(i-e)/2,a=Math.min(o,s*e/2),r=t=>{const e=(i-Math.min(o,t))*s/2;return jt(t,0,Math.min(o,e))};return{outerStart:r(n.outerStart),outerEnd:r(n.outerEnd),innerStart:jt(n.innerStart,0,a),innerEnd:jt(n.innerEnd,0,a)}}function zn(t,e,i,s){return{x:i+t*Math.cos(e),y:s+t*Math.sin(e)}}function Fn(t,e,i,s,n){const{x:o,y:a,startAngle:r,pixelMargin:l,innerRadius:h}=e,c=Math.max(e.outerRadius+s+i-l,0),d=h>0?h+s+i+l:0;let u=0;const f=n-r;if(s){const t=((h>0?h-s:0)+(c>0?c-s:0))/2;u=(f-(0!==t?f*t/(t+s):f))/2}const g=(f-Math.max(.001,f*c-i/_t)/c)/2,p=r+g+u,m=n-g-u,{outerStart:x,outerEnd:b,innerStart:_,innerEnd:y}=In(e,d,c,m-p),v=c-x,w=c-b,M=p+x/v,k=m-b/w,S=d+_,P=d+y,D=p+_/S,C=m-y/P;if(t.beginPath(),t.arc(o,a,c,M,k),b>0){const e=zn(w,k,o,a);t.arc(e.x,e.y,b,k,m+kt)}const O=zn(P,m,o,a);if(t.lineTo(O.x,O.y),y>0){const e=zn(P,C,o,a);t.arc(e.x,e.y,y,m+kt,C+Math.PI)}if(t.arc(o,a,d,m-y/d,p+_/d,!0),_>0){const e=zn(S,D,o,a);t.arc(e.x,e.y,_,D+Math.PI,p-kt)}const A=zn(v,p,o,a);if(t.lineTo(A.x,A.y),x>0){const e=zn(v,M,o,a);t.arc(e.x,e.y,x,p-kt,M)}t.closePath()}function Bn(t,e,i,s,n){const{options:o}=e,{borderWidth:a,borderJoinStyle:r}=o,l="inner"===o.borderAlign;a&&(l?(t.lineWidth=2*a,t.lineJoin=r||"round"):(t.lineWidth=a,t.lineJoin=r||"bevel"),e.fullCircles&&function(t,e,i){const{x:s,y:n,startAngle:o,pixelMargin:a,fullCircles:r}=e,l=Math.max(e.outerRadius-a,0),h=e.innerRadius+a;let c;for(i&&En(t,e,o+yt),t.beginPath(),t.arc(s,n,h,o+yt,o,!0),c=0;c<r;++c)t.stroke();for(t.beginPath(),t.arc(s,n,l,o,o+yt),c=0;c<r;++c)t.stroke()}(t,e,l),l&&En(t,e,n),Fn(t,e,i,s,n),t.stroke())}class Vn extends Ds{constructor(t){super(),this.options=void 0,this.circumference=void 0,this.startAngle=void 0,this.endAngle=void 0,this.innerRadius=void 0,this.outerRadius=void 0,this.pixelMargin=0,this.fullCircles=0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.getProps(["x","y"],i),{angle:n,distance:o}=Bt(s,{x:t,y:e}),{startAngle:a,endAngle:r,innerRadius:l,outerRadius:h,circumference:c}=this.getProps(["startAngle","endAngle","innerRadius","outerRadius","circumference"],i),d=this.options.spacing/2,u=K(c,r-a)>=yt||Ht(n,a,r),f=Yt(o,l+d,h+d);return u&&f}getCenterPoint(t){const{x:e,y:i,startAngle:s,endAngle:n,innerRadius:o,outerRadius:a}=this.getProps(["x","y","startAngle","endAngle","innerRadius","outerRadius","circumference"],t),{offset:r,spacing:l}=this.options,h=(s+n)/2,c=(o+a+l+r)/2;return{x:e+Math.cos(h)*c,y:i+Math.sin(h)*c}}tooltipPosition(t){return this.getCenterPoint(t)}draw(t){const{options:e,circumference:i}=this,s=(e.offset||0)/2,n=(e.spacing||0)/2;if(this.pixelMargin="inner"===e.borderAlign?.33:0,this.fullCircles=i>yt?Math.floor(i/yt):0,0===i||this.innerRadius<0||this.outerRadius<0)return;t.save();let o=0;if(s){o=s/2;const e=(this.startAngle+this.endAngle)/2;t.translate(Math.cos(e)*o,Math.sin(e)*o),this.circumference>=_t&&(o=s)}t.fillStyle=e.backgroundColor,t.strokeStyle=e.borderColor;const a=function(t,e,i,s){const{fullCircles:n,startAngle:o,circumference:a}=e;let r=e.endAngle;if(n){Fn(t,e,i,s,o+yt);for(let e=0;e<n;++e)t.fill();isNaN(a)||(r=o+a%yt,a%yt==0&&(r+=yt))}return Fn(t,e,i,s,r),t.fill(),r}(t,this,o,n);Bn(t,this,o,n,a),t.restore()}}function Wn(t,e,i=e){t.lineCap=K(i.borderCapStyle,e.borderCapStyle),t.setLineDash(K(i.borderDash,e.borderDash)),t.lineDashOffset=K(i.borderDashOffset,e.borderDashOffset),t.lineJoin=K(i.borderJoinStyle,e.borderJoinStyle),t.lineWidth=K(i.borderWidth,e.borderWidth),t.strokeStyle=K(i.borderColor,e.borderColor)}function Nn(t,e,i){t.lineTo(i.x,i.y)}function Hn(t,e,i={}){const s=t.length,{start:n=0,end:o=s-1}=i,{start:a,end:r}=e,l=Math.max(n,a),h=Math.min(o,r),c=n<a&&o<a||n>r&&o>r;return{count:s,start:l,loop:e.loop,ilen:h<l&&!c?s+h-l:h-l}}function jn(t,e,i,s){const{points:n,options:o}=e,{count:a,start:r,loop:l,ilen:h}=Hn(n,i,s),c=function(t){return t.stepped?ee:t.tension||"monotone"===t.cubicInterpolationMode?ie:Nn}(o);let d,u,f,{move:g=!0,reverse:p}=s||{};for(d=0;d<=h;++d)u=n[(r+(p?h-d:d))%a],u.skip||(g?(t.moveTo(u.x,u.y),g=!1):c(t,f,u,p,o.stepped),f=u);return l&&(u=n[(r+(p?h:0))%a],c(t,f,u,p,o.stepped)),!!l}function $n(t,e,i,s){const n=e.points,{count:o,start:a,ilen:r}=Hn(n,i,s),{move:l=!0,reverse:h}=s||{};let c,d,u,f,g,p,m=0,x=0;const b=t=>(a+(h?r-t:t))%o,_=()=>{f!==g&&(t.lineTo(m,g),t.lineTo(m,f),t.lineTo(m,p))};for(l&&(d=n[b(0)],t.moveTo(d.x,d.y)),c=0;c<=r;++c){if(d=n[b(c)],d.skip)continue;const e=d.x,i=d.y,s=0|e;s===u?(i<f?f=i:i>g&&(g=i),m=(x*m+e)/++x):(_(),t.lineTo(e,i),u=s,x=0,f=g=i),p=i}_()}function Yn(t){const e=t.options,i=e.borderDash&&e.borderDash.length;return!(t._decimated||t._loop||e.tension||"monotone"===e.cubicInterpolationMode||e.stepped||i)?$n:jn}Vn.id="arc",Vn.defaults={borderAlign:"center",borderColor:"#fff",borderJoinStyle:void 0,borderRadius:0,borderWidth:2,offset:0,spacing:0,angle:void 0},Vn.defaultRoutes={backgroundColor:"backgroundColor"};const Un="function"==typeof Path2D;function Xn(t,e,i,s){Un&&!e.options.segment?function(t,e,i,s){let n=e._path;n||(n=e._path=new Path2D,e.path(n,i,s)&&n.closePath()),Wn(t,e.options),t.stroke(n)}(t,e,i,s):function(t,e,i,s){const{segments:n,options:o}=e,a=Yn(e);for(const r of n)Wn(t,o,r.style),t.beginPath(),a(t,e,r,{start:i,end:i+s-1})&&t.closePath(),t.stroke()}(t,e,i,s)}class qn extends Ds{constructor(t){super(),this.animated=!0,this.options=void 0,this._chart=void 0,this._loop=void 0,this._fullLoop=void 0,this._path=void 0,this._points=void 0,this._segments=void 0,this._decimated=!1,this._pointsUpdated=!1,this._datasetIndex=void 0,t&&Object.assign(this,t)}updateControlPoints(t,e){const i=this.options;if((i.tension||"monotone"===i.cubicInterpolationMode)&&!i.stepped&&!this._pointsUpdated){const s=i.spanGaps?this._loop:this._fullLoop;ki(this._points,i,t,s,e),this._pointsUpdated=!0}}set points(t){this._points=t,delete this._segments,delete this._path,this._pointsUpdated=!1}get points(){return this._points}get segments(){return this._segments||(this._segments=Ni(this,this.options.segment))}first(){const t=this.segments,e=this.points;return t.length&&e[t[0].start]}last(){const t=this.segments,e=this.points,i=t.length;return i&&e[t[i-1].end]}interpolate(t,e){const i=this.options,s=t[e],n=this.points,o=Wi(this,{property:e,start:s,end:s});if(!o.length)return;const a=[],r=function(t){return t.stepped?Ai:t.tension||"monotone"===t.cubicInterpolationMode?Ti:Oi}(i);let l,h;for(l=0,h=o.length;l<h;++l){const{start:h,end:c}=o[l],d=n[h],u=n[c];if(d===u){a.push(d);continue}const f=r(d,u,Math.abs((s-d[e])/(u[e]-d[e])),i.stepped);f[e]=t[e],a.push(f)}return 1===a.length?a[0]:a}pathSegment(t,e,i){return Yn(this)(t,this,e,i)}path(t,e,i){const s=this.segments,n=Yn(this);let o=this._loop;e=e||0,i=i||this.points.length-e;for(const a of s)o&=n(t,this,a,{start:e,end:e+i-1});return!!o}draw(t,e,i,s){const n=this.options||{};(this.points||[]).length&&n.borderWidth&&(t.save(),Xn(t,this,i,s),t.restore()),this.animated&&(this._pointsUpdated=!1,this._path=void 0)}}function Kn(t,e,i,s){const n=t.options,{[i]:o}=t.getProps([i],s);return Math.abs(e-o)<n.radius+n.hitRadius}qn.id="line",qn.defaults={borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderWidth:3,capBezierPoints:!0,cubicInterpolationMode:"default",fill:!1,spanGaps:!1,stepped:!1,tension:0},qn.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"},qn.descriptors={_scriptable:!0,_indexable:t=>"borderDash"!==t&&"fill"!==t};class Gn extends Ds{constructor(t){super(),this.options=void 0,this.parsed=void 0,this.skip=void 0,this.stop=void 0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.options,{x:n,y:o}=this.getProps(["x","y"],i);return Math.pow(t-n,2)+Math.pow(e-o,2)<Math.pow(s.hitRadius+s.radius,2)}inXRange(t,e){return Kn(this,t,"x",e)}inYRange(t,e){return Kn(this,t,"y",e)}getCenterPoint(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}size(t){let e=(t=t||this.options||{}).radius||0;e=Math.max(e,e&&t.hoverRadius||0);return 2*(e+(e&&t.borderWidth||0))}draw(t,e){const i=this.options;this.skip||i.radius<.1||!Jt(this,e,this.size(i)/2)||(t.strokeStyle=i.borderColor,t.lineWidth=i.borderWidth,t.fillStyle=i.backgroundColor,Zt(t,i,this.x,this.y))}getRange(){const t=this.options||{};return t.radius+t.hitRadius}}function Zn(t,e){const{x:i,y:s,base:n,width:o,height:a}=t.getProps(["x","y","base","width","height"],e);let r,l,h,c,d;return t.horizontal?(d=a/2,r=Math.min(i,n),l=Math.max(i,n),h=s-d,c=s+d):(d=o/2,r=i-d,l=i+d,h=Math.min(s,n),c=Math.max(s,n)),{left:r,top:h,right:l,bottom:c}}function Jn(t,e,i,s){return t?0:jt(e,i,s)}function Qn(t){const e=Zn(t),i=e.right-e.left,s=e.bottom-e.top,n=function(t,e,i){const s=t.options.borderWidth,n=t.borderSkipped,o=Ve(s);return{t:Jn(n.top,o.top,0,i),r:Jn(n.right,o.right,0,e),b:Jn(n.bottom,o.bottom,0,i),l:Jn(n.left,o.left,0,e)}}(t,i/2,s/2),o=function(t,e,i){const{enableBorderRadius:s}=t.getProps(["enableBorderRadius"]),n=t.options.borderRadius,o=We(n),a=Math.min(e,i),r=t.borderSkipped,l=s||U(n);return{topLeft:Jn(!l||r.top||r.left,o.topLeft,0,a),topRight:Jn(!l||r.top||r.right,o.topRight,0,a),bottomLeft:Jn(!l||r.bottom||r.left,o.bottomLeft,0,a),bottomRight:Jn(!l||r.bottom||r.right,o.bottomRight,0,a)}}(t,i/2,s/2);return{outer:{x:e.left,y:e.top,w:i,h:s,radius:o},inner:{x:e.left+n.l,y:e.top+n.t,w:i-n.l-n.r,h:s-n.t-n.b,radius:{topLeft:Math.max(0,o.topLeft-Math.max(n.t,n.l)),topRight:Math.max(0,o.topRight-Math.max(n.t,n.r)),bottomLeft:Math.max(0,o.bottomLeft-Math.max(n.b,n.l)),bottomRight:Math.max(0,o.bottomRight-Math.max(n.b,n.r))}}}}function to(t,e,i,s){const n=null===e,o=null===i,a=t&&!(n&&o)&&Zn(t,s);return a&&(n||Yt(e,a.left,a.right))&&(o||Yt(i,a.top,a.bottom))}function eo(t,e){t.rect(e.x,e.y,e.w,e.h)}function io(t,e,i={}){const s=t.x!==i.x?-e:0,n=t.y!==i.y?-e:0,o=(t.x+t.w!==i.x+i.w?e:0)-s,a=(t.y+t.h!==i.y+i.h?e:0)-n;return{x:t.x+s,y:t.y+n,w:t.w+o,h:t.h+a,radius:t.radius}}Gn.id="point",Gn.defaults={borderWidth:1,hitRadius:1,hoverBorderWidth:1,hoverRadius:4,pointStyle:"circle",radius:3,rotation:0},Gn.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};class so extends Ds{constructor(t){super(),this.options=void 0,this.horizontal=void 0,this.base=void 0,this.width=void 0,this.height=void 0,this.inflateAmount=void 0,t&&Object.assign(this,t)}draw(t){const{inflateAmount:e,options:{borderColor:i,backgroundColor:s}}=this,{inner:n,outer:o}=Qn(this),a=(r=o.radius).topLeft||r.topRight||r.bottomLeft||r.bottomRight?oe:eo;var r;t.save(),o.w===n.w&&o.h===n.h||(t.beginPath(),a(t,io(o,e,n)),t.clip(),a(t,io(n,-e,o)),t.fillStyle=i,t.fill("evenodd")),t.beginPath(),a(t,io(n,e)),t.fillStyle=s,t.fill(),t.restore()}inRange(t,e,i){return to(this,t,e,i)}inXRange(t,e){return to(this,t,null,e)}inYRange(t,e){return to(this,null,t,e)}getCenterPoint(t){const{x:e,y:i,base:s,horizontal:n}=this.getProps(["x","y","base","horizontal"],t);return{x:n?(e+s)/2:e,y:n?i:(i+s)/2}}getRange(t){return"x"===t?this.width/2:this.height/2}}so.id="bar",so.defaults={borderSkipped:"start",borderWidth:0,borderRadius:0,inflateAmount:"auto",pointStyle:void 0},so.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};var no=Object.freeze({__proto__:null,ArcElement:Vn,LineElement:qn,PointElement:Gn,BarElement:so});function oo(t){if(t._decimated){const e=t._data;delete t._decimated,delete t._data,Object.defineProperty(t,"data",{value:e})}}function ao(t){t.data.datasets.forEach((t=>{oo(t)}))}var ro={id:"decimation",defaults:{algorithm:"min-max",enabled:!1},beforeElementsUpdate:(t,e,i)=>{if(!i.enabled)return void ao(t);const s=t.width;t.data.datasets.forEach(((e,n)=>{const{_data:o,indexAxis:a}=e,r=t.getDatasetMeta(n),l=o||e.data;if("y"===je([a,t.options.indexAxis]))return;if("line"!==r.type)return;const h=t.scales[r.xAxisID];if("linear"!==h.type&&"time"!==h.type)return;if(t.options.parsing)return;let{start:c,count:d}=function(t,e){const i=e.length;let s,n=0;const{iScale:o}=t,{min:a,max:r,minDefined:l,maxDefined:h}=o.getUserBounds();return l&&(n=jt(re(e,o.axis,a).lo,0,i-1)),s=h?jt(re(e,o.axis,r).hi+1,n,i)-n:i-n,{start:n,count:s}}(r,l);if(d<=(i.threshold||4*s))return void oo(e);let u;switch($(o)&&(e._data=l,delete e.data,Object.defineProperty(e,"data",{configurable:!0,enumerable:!0,get:function(){return this._decimated},set:function(t){this._data=t}})),i.algorithm){case"lttb":u=function(t,e,i,s,n){const o=n.samples||s;if(o>=i)return t.slice(e,e+i);const a=[],r=(i-2)/(o-2);let l=0;const h=e+i-1;let c,d,u,f,g,p=e;for(a[l++]=t[p],c=0;c<o-2;c++){let s,n=0,o=0;const h=Math.floor((c+1)*r)+1+e,m=Math.min(Math.floor((c+2)*r)+1,i)+e,x=m-h;for(s=h;s<m;s++)n+=t[s].x,o+=t[s].y;n/=x,o/=x;const b=Math.floor(c*r)+1+e,_=Math.min(Math.floor((c+1)*r)+1,i)+e,{x:y,y:v}=t[p];for(u=f=-1,s=b;s<_;s++)f=.5*Math.abs((y-n)*(t[s].y-v)-(y-t[s].x)*(o-v)),f>u&&(u=f,d=t[s],g=s);a[l++]=d,p=g}return a[l++]=t[h],a}(l,c,d,s,i);break;case"min-max":u=function(t,e,i,s){let n,o,a,r,l,h,c,d,u,f,g=0,p=0;const m=[],x=e+i-1,b=t[e].x,_=t[x].x-b;for(n=e;n<e+i;++n){o=t[n],a=(o.x-b)/_*s,r=o.y;const e=0|a;if(e===l)r<u?(u=r,h=n):r>f&&(f=r,c=n),g=(p*g+o.x)/++p;else{const i=n-1;if(!$(h)&&!$(c)){const e=Math.min(h,c),s=Math.max(h,c);e!==d&&e!==i&&m.push({...t[e],x:g}),s!==d&&s!==i&&m.push({...t[s],x:g})}n>0&&i!==d&&m.push(t[i]),m.push(o),l=e,p=0,u=f=r,h=c=d=n}}return m}(l,c,d,s);break;default:throw new Error(`Unsupported decimation algorithm '${i.algorithm}'`)}e._decimated=u}))},destroy(t){ao(t)}};function lo(t,e,i){const s=function(t){const e=t.options,i=e.fill;let s=K(i&&i.target,i);return void 0===s&&(s=!!e.backgroundColor),!1!==s&&null!==s&&(!0===s?"origin":s)}(t);if(U(s))return!isNaN(s.value)&&s;let n=parseFloat(s);return X(n)&&Math.floor(n)===n?("-"!==s[0]&&"+"!==s[0]||(n=e+n),!(n===e||n<0||n>=i)&&n):["origin","start","end","stack","shape"].indexOf(s)>=0&&s}class ho{constructor(t){this.x=t.x,this.y=t.y,this.radius=t.radius}pathSegment(t,e,i){const{x:s,y:n,radius:o}=this;return e=e||{start:0,end:yt},t.arc(s,n,o,e.end,e.start,!0),!i.bounds}interpolate(t){const{x:e,y:i,radius:s}=this,n=t.angle;return{x:e+Math.cos(n)*s,y:i+Math.sin(n)*s,angle:n}}}function co(t){return(t.scale||{}).getPointPositionForValue?function(t){const{scale:e,fill:i}=t,s=e.options,n=e.getLabels().length,o=[],a=s.reverse?e.max:e.min,r=s.reverse?e.min:e.max;let l,h,c;if(c="start"===i?a:"end"===i?r:U(i)?i.value:e.getBaseValue(),s.grid.circular)return h=e.getPointPositionForValue(0,a),new ho({x:h.x,y:h.y,radius:e.getDistanceFromCenterForValue(c)});for(l=0;l<n;++l)o.push(e.getPointPositionForValue(l,c));return o}(t):function(t){const{scale:e={},fill:i}=t;let s,n=null;return"start"===i?n=e.bottom:"end"===i?n=e.top:U(i)?n=e.getPixelForValue(i.value):e.getBasePixel&&(n=e.getBasePixel()),X(n)?(s=e.isHorizontal(),{x:s?n:null,y:s?null:n}):null}(t)}function uo(t,e,i){for(;e>t;e--){const t=i[e];if(!isNaN(t.x)&&!isNaN(t.y))break}return e}function fo(t,e,i){const s=[];for(let n=0;n<i.length;n++){const o=i[n],{first:a,last:r,point:l}=go(o,e,"x");if(!(!l||a&&r))if(a)s.unshift(l);else if(t.push(l),!r)break}t.push(...s)}function go(t,e,i){const s=t.interpolate(e,i);if(!s)return{};const n=s[i],o=t.segments,a=t.points;let r=!1,l=!1;for(let t=0;t<o.length;t++){const e=o[t],s=a[e.start][i],h=a[e.end][i];if(Yt(n,s,h)){r=n===s,l=n===h;break}}return{first:r,last:l,point:s}}function po(t){const{chart:e,fill:i,line:s}=t;if(X(i))return function(t,e){const i=t.getDatasetMeta(e);return i&&t.isDatasetVisible(e)?i.dataset:null}(e,i);if("stack"===i)return function(t){const{scale:e,index:i,line:s}=t,n=[],o=s.segments,a=s.points,r=function(t,e){const i=[],s=t.getMatchingVisibleMetas("line");for(let t=0;t<s.length;t++){const n=s[t];if(n.index===e)break;n.hidden||i.unshift(n.dataset)}return i}(e,i);r.push(mo({x:null,y:e.bottom},s));for(let t=0;t<o.length;t++){const e=o[t];for(let t=e.start;t<=e.end;t++)fo(n,a[t],r)}return new qn({points:n,options:{}})}(t);if("shape"===i)return!0;const n=co(t);return n instanceof ho?n:mo(n,s)}function mo(t,e){let i=[],s=!1;return Y(t)?(s=!0,i=t):i=function(t,e){const{x:i=null,y:s=null}=t||{},n=e.points,o=[];return e.segments.forEach((({start:t,end:e})=>{e=uo(t,e,n);const a=n[t],r=n[e];null!==s?(o.push({x:a.x,y:s}),o.push({x:r.x,y:s})):null!==i&&(o.push({x:i,y:a.y}),o.push({x:i,y:r.y}))})),o}(t,e),i.length?new qn({points:i,options:{tension:0},_loop:s,_fullLoop:s}):null}function xo(t,e,i){let s=t[e].fill;const n=[e];let o;if(!i)return s;for(;!1!==s&&-1===n.indexOf(s);){if(!X(s))return s;if(o=t[s],!o)return!1;if(o.visible)return s;n.push(s),s=o.fill}return!1}function bo(t,e,i){t.beginPath(),e.path(t),t.lineTo(e.last().x,i),t.lineTo(e.first().x,i),t.closePath(),t.clip()}function _o(t,e,i,s){if(s)return;let n=e[t],o=i[t];return"angle"===t&&(n=Nt(n),o=Nt(o)),{property:t,start:n,end:o}}function yo(t,e,i,s){return t&&e?s(t[i],e[i]):t?t[i]:e?e[i]:0}function vo(t,e,i){const{top:s,bottom:n}=e.chart.chartArea,{property:o,start:a,end:r}=i||{};"x"===o&&(t.beginPath(),t.rect(a,s,r-a,n-s),t.clip())}function wo(t,e,i,s){const n=e.interpolate(i,s);n&&t.lineTo(n.x,n.y)}function Mo(t,e){const{line:i,target:s,property:n,color:o,scale:a}=e,r=function(t,e,i){const s=t.segments,n=t.points,o=e.points,a=[];for(const t of s){let{start:s,end:r}=t;r=uo(s,r,n);const l=_o(i,n[s],n[r],t.loop);if(!e.segments){a.push({source:t,target:l,start:n[s],end:n[r]});continue}const h=Wi(e,l);for(const e of h){const s=_o(i,o[e.start],o[e.end],e.loop),r=Vi(t,n,s);for(const t of r)a.push({source:t,target:e,start:{[i]:yo(l,s,"start",Math.max)},end:{[i]:yo(l,s,"end",Math.min)}})}}return a}(i,s,n);for(const{source:e,target:l,start:h,end:c}of r){const{style:{backgroundColor:r=o}={}}=e,d=!0!==s;t.save(),t.fillStyle=r,vo(t,a,d&&_o(n,h,c)),t.beginPath();const u=!!i.pathSegment(t,e);let f;if(d){u?t.closePath():wo(t,s,c,n);const e=!!s.pathSegment(t,l,{move:u,reverse:!0});f=u&&e,f||wo(t,s,h,n)}t.closePath(),t.fill(f?"evenodd":"nonzero"),t.restore()}}function ko(t,e,i){const s=po(e),{line:n,scale:o,axis:a}=e,r=n.options,l=r.fill,h=r.backgroundColor,{above:c=h,below:d=h}=l||{};s&&n.points.length&&(Qt(t,i),function(t,e){const{line:i,target:s,above:n,below:o,area:a,scale:r}=e,l=i._loop?"angle":e.axis;t.save(),"x"===l&&o!==n&&(bo(t,s,a.top),Mo(t,{line:i,target:s,color:n,scale:r,property:l}),t.restore(),t.save(),bo(t,s,a.bottom)),Mo(t,{line:i,target:s,color:o,scale:r,property:l}),t.restore()}(t,{line:n,target:s,above:c,below:d,area:i,scale:o,axis:a}),te(t))}var So={id:"filler",afterDatasetsUpdate(t,e,i){const s=(t.data.datasets||[]).length,n=[];let o,a,r,l;for(a=0;a<s;++a)o=t.getDatasetMeta(a),r=o.dataset,l=null,r&&r.options&&r instanceof qn&&(l={visible:t.isDatasetVisible(a),index:a,fill:lo(r,a,s),chart:t,axis:o.controller.options.indexAxis,scale:o.vScale,line:r}),o.$filler=l,n.push(l);for(a=0;a<s;++a)l=n[a],l&&!1!==l.fill&&(l.fill=xo(n,a,i.propagate))},beforeDraw(t,e,i){const s="beforeDraw"===i.drawTime,n=t.getSortedVisibleDatasetMetas(),o=t.chartArea;for(let e=n.length-1;e>=0;--e){const i=n[e].$filler;i&&(i.line.updateControlPoints(o,i.axis),s&&ko(t.ctx,i,o))}},beforeDatasetsDraw(t,e,i){if("beforeDatasetsDraw"!==i.drawTime)return;const s=t.getSortedVisibleDatasetMetas();for(let e=s.length-1;e>=0;--e){const i=s[e].$filler;i&&ko(t.ctx,i,t.chartArea)}},beforeDatasetDraw(t,e,i){const s=e.meta.$filler;s&&!1!==s.fill&&"beforeDatasetDraw"===i.drawTime&&ko(t.ctx,s,t.chartArea)},defaults:{propagate:!0,drawTime:"beforeDatasetDraw"}};const Po=(t,e)=>{let{boxHeight:i=e,boxWidth:s=e}=t;return t.usePointStyle&&(i=Math.min(i,e),s=Math.min(s,e)),{boxWidth:s,boxHeight:i,itemHeight:Math.max(e,i)}};class Do extends Ds{constructor(t){super(),this._added=!1,this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1,this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this.legendItems=void 0,this.columnSizes=void 0,this.lineWidths=void 0,this.maxHeight=void 0,this.maxWidth=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.height=void 0,this.width=void 0,this._margins=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e,i){this.maxWidth=t,this.maxHeight=e,this._margins=i,this.setDimensions(),this.buildLabels(),this.fit()}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=this._margins.left,this.right=this.width):(this.height=this.maxHeight,this.top=this._margins.top,this.bottom=this.height)}buildLabels(){const t=this.options.labels||{};let e=J(t.generateLabels,[this.chart],this)||[];t.filter&&(e=e.filter((e=>t.filter(e,this.chart.data)))),t.sort&&(e=e.sort(((e,i)=>t.sort(e,i,this.chart.data)))),this.options.reverse&&e.reverse(),this.legendItems=e}fit(){const{options:t,ctx:e}=this;if(!t.display)return void(this.width=this.height=0);const i=t.labels,s=He(i.font),n=s.size,o=this._computeTitleHeight(),{boxWidth:a,itemHeight:r}=Po(i,n);let l,h;e.font=s.string,this.isHorizontal()?(l=this.maxWidth,h=this._fitRows(o,n,a,r)+10):(h=this.maxHeight,l=this._fitCols(o,n,a,r)+10),this.width=Math.min(l,t.maxWidth||this.maxWidth),this.height=Math.min(h,t.maxHeight||this.maxHeight)}_fitRows(t,e,i,s){const{ctx:n,maxWidth:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.lineWidths=[0],h=s+a;let c=t;n.textAlign="left",n.textBaseline="middle";let d=-1,u=-h;return this.legendItems.forEach(((t,f)=>{const g=i+e/2+n.measureText(t.text).width;(0===f||l[l.length-1]+g+2*a>o)&&(c+=h,l[l.length-(f>0?0:1)]=0,u+=h,d++),r[f]={left:0,top:u,row:d,width:g,height:s},l[l.length-1]+=g+a})),c}_fitCols(t,e,i,s){const{ctx:n,maxHeight:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.columnSizes=[],h=o-t;let c=a,d=0,u=0,f=0,g=0;return this.legendItems.forEach(((t,o)=>{const p=i+e/2+n.measureText(t.text).width;o>0&&u+s+2*a>h&&(c+=d+a,l.push({width:d,height:u}),f+=d+a,g++,d=u=0),r[o]={left:f,top:u,col:g,width:p,height:s},d=Math.max(d,p),u+=s+a})),c+=d,l.push({width:d,height:u}),c}adjustHitBoxes(){if(!this.options.display)return;const t=this._computeTitleHeight(),{legendHitBoxes:e,options:{align:i,labels:{padding:s},rtl:o}}=this,a=Ei(o,this.left,this.width);if(this.isHorizontal()){let o=0,r=n(i,this.left+s,this.right-this.lineWidths[o]);for(const l of e)o!==l.row&&(o=l.row,r=n(i,this.left+s,this.right-this.lineWidths[o])),l.top+=this.top+t+s,l.left=a.leftForLtr(a.x(r),l.width),r+=l.width+s}else{let o=0,r=n(i,this.top+t+s,this.bottom-this.columnSizes[o].height);for(const l of e)l.col!==o&&(o=l.col,r=n(i,this.top+t+s,this.bottom-this.columnSizes[o].height)),l.top=r,l.left+=this.left+s,l.left=a.leftForLtr(a.x(l.left),l.width),r+=l.height+s}}isHorizontal(){return"top"===this.options.position||"bottom"===this.options.position}draw(){if(this.options.display){const t=this.ctx;Qt(t,this),this._draw(),te(t)}}_draw(){const{options:t,columnSizes:e,lineWidths:i,ctx:s}=this,{align:a,labels:r}=t,l=bt.color,h=Ei(t.rtl,this.left,this.width),c=He(r.font),{color:d,padding:u}=r,f=c.size,g=f/2;let p;this.drawTitle(),s.textAlign=h.textAlign("left"),s.textBaseline="middle",s.lineWidth=.5,s.font=c.string;const{boxWidth:m,boxHeight:x,itemHeight:b}=Po(r,f),_=this.isHorizontal(),y=this._computeTitleHeight();p=_?{x:n(a,this.left+u,this.right-i[0]),y:this.top+u+y,line:0}:{x:this.left+u,y:n(a,this.top+y+u,this.bottom-e[0].height),line:0},Ii(this.ctx,t.textDirection);const v=b+u;this.legendItems.forEach(((w,M)=>{s.strokeStyle=w.fontColor||d,s.fillStyle=w.fontColor||d;const k=s.measureText(w.text).width,S=h.textAlign(w.textAlign||(w.textAlign=r.textAlign)),P=m+g+k;let D=p.x,C=p.y;h.setWidth(this.width),_?M>0&&D+P+u>this.right&&(C=p.y+=v,p.line++,D=p.x=n(a,this.left+u,this.right-i[p.line])):M>0&&C+v>this.bottom&&(D=p.x=D+e[p.line].width+u,p.line++,C=p.y=n(a,this.top+y+u,this.bottom-e[p.line].height));!function(t,e,i){if(isNaN(m)||m<=0||isNaN(x)||x<0)return;s.save();const n=K(i.lineWidth,1);if(s.fillStyle=K(i.fillStyle,l),s.lineCap=K(i.lineCap,"butt"),s.lineDashOffset=K(i.lineDashOffset,0),s.lineJoin=K(i.lineJoin,"miter"),s.lineWidth=n,s.strokeStyle=K(i.strokeStyle,l),s.setLineDash(K(i.lineDash,[])),r.usePointStyle){const o={radius:m*Math.SQRT2/2,pointStyle:i.pointStyle,rotation:i.rotation,borderWidth:n},a=h.xPlus(t,m/2);Zt(s,o,a,e+g)}else{const o=e+Math.max((f-x)/2,0),a=h.leftForLtr(t,m),r=We(i.borderRadius);s.beginPath(),Object.values(r).some((t=>0!==t))?oe(s,{x:a,y:o,w:m,h:x,radius:r}):s.rect(a,o,m,x),s.fill(),0!==n&&s.stroke()}s.restore()}(h.x(D),C,w),D=o(S,D+m+g,_?D+P:this.right,t.rtl),function(t,e,i){se(s,i.text,t,e+b/2,c,{strikethrough:i.hidden,textAlign:h.textAlign(i.textAlign)})}(h.x(D),C,w),_?p.x+=P+u:p.y+=v})),zi(this.ctx,t.textDirection)}drawTitle(){const t=this.options,e=t.title,i=He(e.font),o=Ne(e.padding);if(!e.display)return;const a=Ei(t.rtl,this.left,this.width),r=this.ctx,l=e.position,h=i.size/2,c=o.top+h;let d,u=this.left,f=this.width;if(this.isHorizontal())f=Math.max(...this.lineWidths),d=this.top+c,u=n(t.align,u,this.right-f);else{const e=this.columnSizes.reduce(((t,e)=>Math.max(t,e.height)),0);d=c+n(t.align,this.top,this.bottom-e-t.labels.padding-this._computeTitleHeight())}const g=n(l,u,u+f);r.textAlign=a.textAlign(s(l)),r.textBaseline="middle",r.strokeStyle=e.color,r.fillStyle=e.color,r.font=i.string,se(r,e.text,g,d,i)}_computeTitleHeight(){const t=this.options.title,e=He(t.font),i=Ne(t.padding);return t.display?e.lineHeight+i.height:0}_getLegendItemAt(t,e){let i,s,n;if(Yt(t,this.left,this.right)&&Yt(e,this.top,this.bottom))for(n=this.legendHitBoxes,i=0;i<n.length;++i)if(s=n[i],Yt(t,s.left,s.left+s.width)&&Yt(e,s.top,s.top+s.height))return this.legendItems[i];return null}handleEvent(t){const e=this.options;if(!function(t,e){if("mousemove"===t&&(e.onHover||e.onLeave))return!0;if(e.onClick&&("click"===t||"mouseup"===t))return!0;return!1}(t.type,e))return;const i=this._getLegendItemAt(t.x,t.y);if("mousemove"===t.type){const o=this._hoveredItem,a=(n=i,null!==(s=o)&&null!==n&&s.datasetIndex===n.datasetIndex&&s.index===n.index);o&&!a&&J(e.onLeave,[t,o,this],this),this._hoveredItem=i,i&&!a&&J(e.onHover,[t,i,this],this)}else i&&J(e.onClick,[t,i,this],this);var s,n}}var Co={id:"legend",_element:Do,start(t,e,i){const s=t.legend=new Do({ctx:t.ctx,options:i,chart:t});ni.configure(t,s,i),ni.addBox(t,s)},stop(t){ni.removeBox(t,t.legend),delete t.legend},beforeUpdate(t,e,i){const s=t.legend;ni.configure(t,s,i),s.options=i},afterUpdate(t){const e=t.legend;e.buildLabels(),e.adjustHitBoxes()},afterEvent(t,e){e.replay||t.legend.handleEvent(e.event)},defaults:{display:!0,position:"top",align:"center",fullSize:!0,reverse:!1,weight:1e3,onClick(t,e,i){const s=e.datasetIndex,n=i.chart;n.isDatasetVisible(s)?(n.hide(s),e.hidden=!0):(n.show(s),e.hidden=!1)},onHover:null,onLeave:null,labels:{color:t=>t.chart.options.color,boxWidth:40,padding:10,generateLabels(t){const e=t.data.datasets,{labels:{usePointStyle:i,pointStyle:s,textAlign:n,color:o}}=t.legend.options;return t._getSortedDatasetMetas().map((t=>{const a=t.controller.getStyle(i?0:void 0),r=Ne(a.borderWidth);return{text:e[t.index].label,fillStyle:a.backgroundColor,fontColor:o,hidden:!t.visible,lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:(r.width+r.height)/4,strokeStyle:a.borderColor,pointStyle:s||a.pointStyle,rotation:a.rotation,textAlign:n||a.textAlign,borderRadius:0,datasetIndex:t.index}}),this)}},title:{color:t=>t.chart.options.color,display:!1,position:"center",text:""}},descriptors:{_scriptable:t=>!t.startsWith("on"),labels:{_scriptable:t=>!["generateLabels","filter","sort"].includes(t)}}};class Oo extends Ds{constructor(t){super(),this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this._padding=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e){const i=this.options;if(this.left=0,this.top=0,!i.display)return void(this.width=this.height=this.right=this.bottom=0);this.width=this.right=t,this.height=this.bottom=e;const s=Y(i.text)?i.text.length:1;this._padding=Ne(i.padding);const n=s*He(i.font).lineHeight+this._padding.height;this.isHorizontal()?this.height=n:this.width=n}isHorizontal(){const t=this.options.position;return"top"===t||"bottom"===t}_drawArgs(t){const{top:e,left:i,bottom:s,right:o,options:a}=this,r=a.align;let l,h,c,d=0;return this.isHorizontal()?(h=n(r,i,o),c=e+t,l=o-i):("left"===a.position?(h=i+t,c=n(r,s,e),d=-.5*_t):(h=o-t,c=n(r,e,s),d=.5*_t),l=s-e),{titleX:h,titleY:c,maxWidth:l,rotation:d}}draw(){const t=this.ctx,e=this.options;if(!e.display)return;const i=He(e.font),n=i.lineHeight/2+this._padding.top,{titleX:o,titleY:a,maxWidth:r,rotation:l}=this._drawArgs(n);se(t,e.text,0,0,i,{color:e.color,maxWidth:r,rotation:l,textAlign:s(e.align),textBaseline:"middle",translation:[o,a]})}}var Ao={id:"title",_element:Oo,start(t,e,i){!function(t,e){const i=new Oo({ctx:t.ctx,options:e,chart:t});ni.configure(t,i,e),ni.addBox(t,i),t.titleBlock=i}(t,i)},stop(t){const e=t.titleBlock;ni.removeBox(t,e),delete t.titleBlock},beforeUpdate(t,e,i){const s=t.titleBlock;ni.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"bold"},fullSize:!0,padding:10,position:"top",text:"",weight:2e3},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const To=new WeakMap;var Lo={id:"subtitle",start(t,e,i){const s=new Oo({ctx:t.ctx,options:i,chart:t});ni.configure(t,s,i),ni.addBox(t,s),To.set(t,s)},stop(t){ni.removeBox(t,To.get(t)),To.delete(t)},beforeUpdate(t,e,i){const s=To.get(t);ni.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"normal"},fullSize:!0,padding:0,position:"top",text:"",weight:1500},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Ro={average(t){if(!t.length)return!1;let e,i,s=0,n=0,o=0;for(e=0,i=t.length;e<i;++e){const i=t[e].element;if(i&&i.hasValue()){const t=i.tooltipPosition();s+=t.x,n+=t.y,++o}}return{x:s/o,y:n/o}},nearest(t,e){if(!t.length)return!1;let i,s,n,o=e.x,a=e.y,r=Number.POSITIVE_INFINITY;for(i=0,s=t.length;i<s;++i){const s=t[i].element;if(s&&s.hasValue()){const t=Vt(e,s.getCenterPoint());t<r&&(r=t,n=s)}}if(n){const t=n.tooltipPosition();o=t.x,a=t.y}return{x:o,y:a}}};function Eo(t,e){return e&&(Y(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function Io(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function zo(t,e){const{element:i,datasetIndex:s,index:n}=e,o=t.getDatasetMeta(s).controller,{label:a,value:r}=o.getLabelAndValue(n);return{chart:t,label:a,parsed:o.getParsed(n),raw:t.data.datasets[s].data[n],formattedValue:r,dataset:o.getDataset(),dataIndex:n,datasetIndex:s,element:i}}function Fo(t,e){const i=t.chart.ctx,{body:s,footer:n,title:o}=t,{boxWidth:a,boxHeight:r}=e,l=He(e.bodyFont),h=He(e.titleFont),c=He(e.footerFont),d=o.length,u=n.length,f=s.length,g=Ne(e.padding);let p=g.height,m=0,x=s.reduce(((t,e)=>t+e.before.length+e.lines.length+e.after.length),0);if(x+=t.beforeBody.length+t.afterBody.length,d&&(p+=d*h.lineHeight+(d-1)*e.titleSpacing+e.titleMarginBottom),x){p+=f*(e.displayColors?Math.max(r,l.lineHeight):l.lineHeight)+(x-f)*l.lineHeight+(x-1)*e.bodySpacing}u&&(p+=e.footerMarginTop+u*c.lineHeight+(u-1)*e.footerSpacing);let b=0;const _=function(t){m=Math.max(m,i.measureText(t).width+b)};return i.save(),i.font=h.string,Q(t.title,_),i.font=l.string,Q(t.beforeBody.concat(t.afterBody),_),b=e.displayColors?a+2+e.boxPadding:0,Q(s,(t=>{Q(t.before,_),Q(t.lines,_),Q(t.after,_)})),b=0,i.font=c.string,Q(t.footer,_),i.restore(),m+=g.width,{width:m,height:p}}function Bo(t,e,i,s){const{x:n,width:o}=i,{width:a,chartArea:{left:r,right:l}}=t;let h="center";return"center"===s?h=n<=(r+l)/2?"left":"right":n<=o/2?h="left":n>=a-o/2&&(h="right"),function(t,e,i,s){const{x:n,width:o}=s,a=i.caretSize+i.caretPadding;return"left"===t&&n+o+a>e.width||"right"===t&&n-o-a<0||void 0}(h,t,e,i)&&(h="center"),h}function Vo(t,e,i){const s=i.yAlign||e.yAlign||function(t,e){const{y:i,height:s}=e;return i<s/2?"top":i>t.height-s/2?"bottom":"center"}(t,i);return{xAlign:i.xAlign||e.xAlign||Bo(t,e,i,s),yAlign:s}}function Wo(t,e,i,s){const{caretSize:n,caretPadding:o,cornerRadius:a}=t,{xAlign:r,yAlign:l}=i,h=n+o,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=We(a);let g=function(t,e){let{x:i,width:s}=t;return"right"===e?i-=s:"center"===e&&(i-=s/2),i}(e,r);const p=function(t,e,i){let{y:s,height:n}=t;return"top"===e?s+=i:s-="bottom"===e?n+i:n/2,s}(e,l,h);return"center"===l?"left"===r?g+=h:"right"===r&&(g-=h):"left"===r?g-=Math.max(c,u)+n:"right"===r&&(g+=Math.max(d,f)+n),{x:jt(g,0,s.width-e.width),y:jt(p,0,s.height-e.height)}}function No(t,e,i){const s=Ne(i.padding);return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-s.right:t.x+s.left}function Ho(t){return Eo([],Io(t))}function jo(t,e){const i=e&&e.dataset&&e.dataset.tooltip&&e.dataset.tooltip.callbacks;return i?t.override(i):t}class $o extends Ds{constructor(t){super(),this.opacity=0,this._active=[],this._eventPosition=void 0,this._size=void 0,this._cachedAnimations=void 0,this._tooltipItems=[],this.$animations=void 0,this.$context=void 0,this.chart=t.chart||t._chart,this._chart=this.chart,this.options=t.options,this.dataPoints=void 0,this.title=void 0,this.beforeBody=void 0,this.body=void 0,this.afterBody=void 0,this.footer=void 0,this.xAlign=void 0,this.yAlign=void 0,this.x=void 0,this.y=void 0,this.height=void 0,this.width=void 0,this.caretX=void 0,this.caretY=void 0,this.labelColors=void 0,this.labelPointStyles=void 0,this.labelTextColors=void 0}initialize(t){this.options=t,this._cachedAnimations=void 0,this.$context=void 0}_resolveAnimations(){const t=this._cachedAnimations;if(t)return t;const e=this.chart,i=this.options.setContext(this.getContext()),s=i.enabled&&e.options.animation&&i.animations,n=new gs(this.chart,s);return s._cacheable&&(this._cachedAnimations=Object.freeze(n)),n}getContext(){return this.$context||(this.$context=(t=this.chart.getContext(),e=this,i=this._tooltipItems,Ye(t,{tooltip:e,tooltipItems:i,type:"tooltip"})));var t,e,i}getTitle(t,e){const{callbacks:i}=e,s=i.beforeTitle.apply(this,[t]),n=i.title.apply(this,[t]),o=i.afterTitle.apply(this,[t]);let a=[];return a=Eo(a,Io(s)),a=Eo(a,Io(n)),a=Eo(a,Io(o)),a}getBeforeBody(t,e){return Ho(e.callbacks.beforeBody.apply(this,[t]))}getBody(t,e){const{callbacks:i}=e,s=[];return Q(t,(t=>{const e={before:[],lines:[],after:[]},n=jo(i,t);Eo(e.before,Io(n.beforeLabel.call(this,t))),Eo(e.lines,n.label.call(this,t)),Eo(e.after,Io(n.afterLabel.call(this,t))),s.push(e)})),s}getAfterBody(t,e){return Ho(e.callbacks.afterBody.apply(this,[t]))}getFooter(t,e){const{callbacks:i}=e,s=i.beforeFooter.apply(this,[t]),n=i.footer.apply(this,[t]),o=i.afterFooter.apply(this,[t]);let a=[];return a=Eo(a,Io(s)),a=Eo(a,Io(n)),a=Eo(a,Io(o)),a}_createItems(t){const e=this._active,i=this.chart.data,s=[],n=[],o=[];let a,r,l=[];for(a=0,r=e.length;a<r;++a)l.push(zo(this.chart,e[a]));return t.filter&&(l=l.filter(((e,s,n)=>t.filter(e,s,n,i)))),t.itemSort&&(l=l.sort(((e,s)=>t.itemSort(e,s,i)))),Q(l,(e=>{const i=jo(t.callbacks,e);s.push(i.labelColor.call(this,e)),n.push(i.labelPointStyle.call(this,e)),o.push(i.labelTextColor.call(this,e))})),this.labelColors=s,this.labelPointStyles=n,this.labelTextColors=o,this.dataPoints=l,l}update(t,e){const i=this.options.setContext(this.getContext()),s=this._active;let n,o=[];if(s.length){const t=Ro[i.position].call(this,s,this._eventPosition);o=this._createItems(i),this.title=this.getTitle(o,i),this.beforeBody=this.getBeforeBody(o,i),this.body=this.getBody(o,i),this.afterBody=this.getAfterBody(o,i),this.footer=this.getFooter(o,i);const e=this._size=Fo(this,i),a=Object.assign({},t,e),r=Vo(this.chart,i,a),l=Wo(i,a,r,this.chart);this.xAlign=r.xAlign,this.yAlign=r.yAlign,n={opacity:1,x:l.x,y:l.y,width:e.width,height:e.height,caretX:t.x,caretY:t.y}}else 0!==this.opacity&&(n={opacity:0});this._tooltipItems=o,this.$context=void 0,n&&this._resolveAnimations().update(this,n),t&&i.external&&i.external.call(this,{chart:this.chart,tooltip:this,replay:e})}drawCaret(t,e,i,s){const n=this.getCaretPosition(t,i,s);e.lineTo(n.x1,n.y1),e.lineTo(n.x2,n.y2),e.lineTo(n.x3,n.y3)}getCaretPosition(t,e,i){const{xAlign:s,yAlign:n}=this,{caretSize:o,cornerRadius:a}=i,{topLeft:r,topRight:l,bottomLeft:h,bottomRight:c}=We(a),{x:d,y:u}=t,{width:f,height:g}=e;let p,m,x,b,_,y;return"center"===n?(_=u+g/2,"left"===s?(p=d,m=p-o,b=_+o,y=_-o):(p=d+f,m=p+o,b=_-o,y=_+o),x=p):(m="left"===s?d+Math.max(r,h)+o:"right"===s?d+f-Math.max(l,c)-o:this.caretX,"top"===n?(b=u,_=b-o,p=m-o,x=m+o):(b=u+g,_=b+o,p=m+o,x=m-o),y=b),{x1:p,x2:m,x3:x,y1:b,y2:_,y3:y}}drawTitle(t,e,i){const s=this.title,n=s.length;let o,a,r;if(n){const l=Ei(i.rtl,this.x,this.width);for(t.x=No(this,i.titleAlign,i),e.textAlign=l.textAlign(i.titleAlign),e.textBaseline="middle",o=He(i.titleFont),a=i.titleSpacing,e.fillStyle=i.titleColor,e.font=o.string,r=0;r<n;++r)e.fillText(s[r],l.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+a,r+1===n&&(t.y+=i.titleMarginBottom-a)}}_drawColorBox(t,e,i,s,n){const o=this.labelColors[i],a=this.labelPointStyles[i],{boxHeight:r,boxWidth:l,boxPadding:h}=n,c=He(n.bodyFont),d=No(this,"left",n),u=s.x(d),f=r<c.lineHeight?(c.lineHeight-r)/2:0,g=e.y+f;if(n.usePointStyle){const e={radius:Math.min(l,r)/2,pointStyle:a.pointStyle,rotation:a.rotation,borderWidth:1},i=s.leftForLtr(u,l)+l/2,h=g+r/2;t.strokeStyle=n.multiKeyBackground,t.fillStyle=n.multiKeyBackground,Zt(t,e,i,h),t.strokeStyle=o.borderColor,t.fillStyle=o.backgroundColor,Zt(t,e,i,h)}else{t.lineWidth=o.borderWidth||1,t.strokeStyle=o.borderColor,t.setLineDash(o.borderDash||[]),t.lineDashOffset=o.borderDashOffset||0;const e=s.leftForLtr(u,l-h),i=s.leftForLtr(s.xPlus(u,1),l-h-2),a=We(o.borderRadius);Object.values(a).some((t=>0!==t))?(t.beginPath(),t.fillStyle=n.multiKeyBackground,oe(t,{x:e,y:g,w:l,h:r,radius:a}),t.fill(),t.stroke(),t.fillStyle=o.backgroundColor,t.beginPath(),oe(t,{x:i,y:g+1,w:l-2,h:r-2,radius:a}),t.fill()):(t.fillStyle=n.multiKeyBackground,t.fillRect(e,g,l,r),t.strokeRect(e,g,l,r),t.fillStyle=o.backgroundColor,t.fillRect(i,g+1,l-2,r-2))}t.fillStyle=this.labelTextColors[i]}drawBody(t,e,i){const{body:s}=this,{bodySpacing:n,bodyAlign:o,displayColors:a,boxHeight:r,boxWidth:l,boxPadding:h}=i,c=He(i.bodyFont);let d=c.lineHeight,u=0;const f=Ei(i.rtl,this.x,this.width),g=function(i){e.fillText(i,f.x(t.x+u),t.y+d/2),t.y+=d+n},p=f.textAlign(o);let m,x,b,_,y,v,w;for(e.textAlign=o,e.textBaseline="middle",e.font=c.string,t.x=No(this,p,i),e.fillStyle=i.bodyColor,Q(this.beforeBody,g),u=a&&"right"!==p?"center"===o?l/2+h:l+2+h:0,_=0,v=s.length;_<v;++_){for(m=s[_],x=this.labelTextColors[_],e.fillStyle=x,Q(m.before,g),b=m.lines,a&&b.length&&(this._drawColorBox(e,t,_,f,i),d=Math.max(c.lineHeight,r)),y=0,w=b.length;y<w;++y)g(b[y]),d=c.lineHeight;Q(m.after,g)}u=0,d=c.lineHeight,Q(this.afterBody,g),t.y-=n}drawFooter(t,e,i){const s=this.footer,n=s.length;let o,a;if(n){const r=Ei(i.rtl,this.x,this.width);for(t.x=No(this,i.footerAlign,i),t.y+=i.footerMarginTop,e.textAlign=r.textAlign(i.footerAlign),e.textBaseline="middle",o=He(i.footerFont),e.fillStyle=i.footerColor,e.font=o.string,a=0;a<n;++a)e.fillText(s[a],r.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+i.footerSpacing}}drawBackground(t,e,i,s){const{xAlign:n,yAlign:o}=this,{x:a,y:r}=t,{width:l,height:h}=i,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=We(s.cornerRadius);e.fillStyle=s.backgroundColor,e.strokeStyle=s.borderColor,e.lineWidth=s.borderWidth,e.beginPath(),e.moveTo(a+c,r),"top"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+l-d,r),e.quadraticCurveTo(a+l,r,a+l,r+d),"center"===o&&"right"===n&&this.drawCaret(t,e,i,s),e.lineTo(a+l,r+h-f),e.quadraticCurveTo(a+l,r+h,a+l-f,r+h),"bottom"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+u,r+h),e.quadraticCurveTo(a,r+h,a,r+h-u),"center"===o&&"left"===n&&this.drawCaret(t,e,i,s),e.lineTo(a,r+c),e.quadraticCurveTo(a,r,a+c,r),e.closePath(),e.fill(),s.borderWidth>0&&e.stroke()}_updateAnimationTarget(t){const e=this.chart,i=this.$animations,s=i&&i.x,n=i&&i.y;if(s||n){const i=Ro[t.position].call(this,this._active,this._eventPosition);if(!i)return;const o=this._size=Fo(this,t),a=Object.assign({},i,this._size),r=Vo(e,t,a),l=Wo(t,a,r,e);s._to===l.x&&n._to===l.y||(this.xAlign=r.xAlign,this.yAlign=r.yAlign,this.width=o.width,this.height=o.height,this.caretX=i.x,this.caretY=i.y,this._resolveAnimations().update(this,l))}}draw(t){const e=this.options.setContext(this.getContext());let i=this.opacity;if(!i)return;this._updateAnimationTarget(e);const s={width:this.width,height:this.height},n={x:this.x,y:this.y};i=Math.abs(i)<.001?0:i;const o=Ne(e.padding),a=this.title.length||this.beforeBody.length||this.body.length||this.afterBody.length||this.footer.length;e.enabled&&a&&(t.save(),t.globalAlpha=i,this.drawBackground(n,t,s,e),Ii(t,e.textDirection),n.y+=o.top,this.drawTitle(n,t,e),this.drawBody(n,t,e),this.drawFooter(n,t,e),zi(t,e.textDirection),t.restore())}getActiveElements(){return this._active||[]}setActiveElements(t,e){const i=this._active,s=t.map((({datasetIndex:t,index:e})=>{const i=this.chart.getDatasetMeta(t);if(!i)throw new Error("Cannot find a dataset at index "+t);return{datasetIndex:t,element:i.data[e],index:e}})),n=!tt(i,s),o=this._positionChanged(s,e);(n||o)&&(this._active=s,this._eventPosition=e,this._ignoreReplayEvents=!0,this.update(!0))}handleEvent(t,e,i=!0){if(e&&this._ignoreReplayEvents)return!1;this._ignoreReplayEvents=!1;const s=this.options,n=this._active||[],o=this._getActiveElements(t,n,e,i),a=this._positionChanged(o,t),r=e||!tt(o,n)||a;return r&&(this._active=o,(s.enabled||s.external)&&(this._eventPosition={x:t.x,y:t.y},this.update(!0,e))),r}_getActiveElements(t,e,i,s){const n=this.options;if("mouseout"===t.type)return[];if(!s)return e;const o=this.chart.getElementsAtEventForMode(t,n.mode,n,i);return n.reverse&&o.reverse(),o}_positionChanged(t,e){const{caretX:i,caretY:s,options:n}=this,o=Ro[n.position].call(this,t,e);return!1!==o&&(i!==o.x||s!==o.y)}}$o.positioners=Ro;var Yo={id:"tooltip",_element:$o,positioners:Ro,afterInit(t,e,i){i&&(t.tooltip=new $o({chart:t,options:i}))},beforeUpdate(t,e,i){t.tooltip&&t.tooltip.initialize(i)},reset(t,e,i){t.tooltip&&t.tooltip.initialize(i)},afterDraw(t){const e=t.tooltip,i={tooltip:e};!1!==t.notifyPlugins("beforeTooltipDraw",i)&&(e&&e.draw(t.ctx),t.notifyPlugins("afterTooltipDraw",i))},afterEvent(t,e){if(t.tooltip){const i=e.replay;t.tooltip.handleEvent(e.event,i,e.inChartArea)&&(e.changed=!0)}},defaults:{enabled:!0,external:null,position:"average",backgroundColor:"rgba(0,0,0,0.8)",titleColor:"#fff",titleFont:{weight:"bold"},titleSpacing:2,titleMarginBottom:6,titleAlign:"left",bodyColor:"#fff",bodySpacing:2,bodyFont:{},bodyAlign:"left",footerColor:"#fff",footerSpacing:2,footerMarginTop:6,footerFont:{weight:"bold"},footerAlign:"left",padding:6,caretPadding:2,caretSize:5,cornerRadius:6,boxHeight:(t,e)=>e.bodyFont.size,boxWidth:(t,e)=>e.bodyFont.size,multiKeyBackground:"#fff",displayColors:!0,boxPadding:0,borderColor:"rgba(0,0,0,0)",borderWidth:0,animation:{duration:400,easing:"easeOutQuart"},animations:{numbers:{type:"number",properties:["x","y","width","height","caretX","caretY"]},opacity:{easing:"linear",duration:200}},callbacks:{beforeTitle:H,title(t){if(t.length>0){const e=t[0],i=e.chart.data.labels,s=i?i.length:0;if(this&&this.options&&"dataset"===this.options.mode)return e.dataset.label||"";if(e.label)return e.label;if(s>0&&e.dataIndex<s)return i[e.dataIndex]}return""},afterTitle:H,beforeBody:H,beforeLabel:H,label(t){if(this&&this.options&&"dataset"===this.options.mode)return t.label+": "+t.formattedValue||t.formattedValue;let e=t.dataset.label||"";e&&(e+=": ");const i=t.formattedValue;return $(i)||(e+=i),e},labelColor(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{borderColor:e.borderColor,backgroundColor:e.backgroundColor,borderWidth:e.borderWidth,borderDash:e.borderDash,borderDashOffset:e.borderDashOffset,borderRadius:0}},labelTextColor(){return this.options.bodyColor},labelPointStyle(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{pointStyle:e.pointStyle,rotation:e.rotation}},afterLabel:H,afterBody:H,beforeFooter:H,footer:H,afterFooter:H}},defaultRoutes:{bodyFont:"font",footerFont:"font",titleFont:"font"},descriptors:{_scriptable:t=>"filter"!==t&&"itemSort"!==t&&"external"!==t,_indexable:!1,callbacks:{_scriptable:!1,_indexable:!1},animation:{_fallback:!1},animations:{_fallback:"animation"}},additionalOptionScopes:["interaction"]},Uo=Object.freeze({__proto__:null,Decimation:ro,Filler:So,Legend:Co,SubTitle:Lo,Title:Ao,Tooltip:Yo});function Xo(t,e,i,s){const n=t.indexOf(e);if(-1===n)return((t,e,i,s)=>("string"==typeof e?(i=t.push(e)-1,s.unshift({index:i,label:e})):isNaN(e)&&(i=null),i))(t,e,i,s);return n!==t.lastIndexOf(e)?i:n}class qo extends Bs{constructor(t){super(t),this._startValue=void 0,this._valueRange=0,this._addedLabels=[]}init(t){const e=this._addedLabels;if(e.length){const t=this.getLabels();for(const{index:i,label:s}of e)t[i]===s&&t.splice(i,1);this._addedLabels=[]}super.init(t)}parse(t,e){if($(t))return null;const i=this.getLabels();return((t,e)=>null===t?null:jt(Math.round(t),0,e))(e=isFinite(e)&&i[e]===t?e:Xo(i,t,K(e,t),this._addedLabels),i.length-1)}determineDataLimits(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let{min:i,max:s}=this.getMinMax(!0);"ticks"===this.options.bounds&&(t||(i=0),e||(s=this.getLabels().length-1)),this.min=i,this.max=s}buildTicks(){const t=this.min,e=this.max,i=this.options.offset,s=[];let n=this.getLabels();n=0===t&&e===n.length-1?n:n.slice(t,e+1),this._valueRange=Math.max(n.length-(i?0:1),1),this._startValue=this.min-(i?.5:0);for(let i=t;i<=e;i++)s.push({value:i});return s}getLabelForValue(t){const e=this.getLabels();return t>=0&&t<e.length?e[t]:t}configure(){super.configure(),this.isHorizontal()||(this._reversePixels=!this._reversePixels)}getPixelForValue(t){return"number"!=typeof t&&(t=this.parse(t)),null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getValueForPixel(t){return Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange)}getBasePixel(){return this.bottom}}function Ko(t,e,{horizontal:i,minRotation:s}){const n=It(s),o=(i?Math.sin(n):Math.cos(n))||.001,a=.75*e*(""+t).length;return Math.min(e/o,a)}qo.id="category",qo.defaults={ticks:{callback:qo.prototype.getLabelForValue}};class Go extends Bs{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._endValue=void 0,this._valueRange=0}parse(t,e){return $(t)||("number"==typeof t||t instanceof Number)&&!isFinite(+t)?null:+t}handleTickRangeOptions(){const{beginAtZero:t}=this.options,{minDefined:e,maxDefined:i}=this.getUserBounds();let{min:s,max:n}=this;const o=t=>s=e?s:t,a=t=>n=i?n:t;if(t){const t=Ct(s),e=Ct(n);t<0&&e<0?a(0):t>0&&e>0&&o(0)}if(s===n){let e=1;(n>=Number.MAX_SAFE_INTEGER||s<=Number.MIN_SAFE_INTEGER)&&(e=Math.abs(.05*n)),a(n+e),t||o(s-e)}this.min=s,this.max=n}getTickLimit(){const t=this.options.ticks;let e,{maxTicksLimit:i,stepSize:s}=t;return s?(e=Math.ceil(this.max/s)-Math.floor(this.min/s)+1,e>1e3&&(console.warn(`scales.${this.id}.ticks.stepSize: ${s} would result generating up to ${e} ticks. Limiting to 1000.`),e=1e3)):(e=this.computeTickLimit(),i=i||11),i&&(e=Math.min(i,e)),e}computeTickLimit(){return Number.POSITIVE_INFINITY}buildTicks(){const t=this.options,e=t.ticks;let i=this.getTickLimit();i=Math.max(2,i);const s=function(t,e){const i=[],{bounds:s,step:n,min:o,max:a,precision:r,count:l,maxTicks:h,maxDigits:c,includeBounds:d}=t,u=n||1,f=h-1,{min:g,max:p}=e,m=!$(o),x=!$(a),b=!$(l),_=(p-g)/(c+1);let y,v,w,M,k=Ot((p-g)/f/u)*u;if(k<1e-14&&!m&&!x)return[{value:g},{value:p}];M=Math.ceil(p/k)-Math.floor(g/k),M>f&&(k=Ot(M*k/f/u)*u),$(r)||(y=Math.pow(10,r),k=Math.ceil(k*y)/y),"ticks"===s?(v=Math.floor(g/k)*k,w=Math.ceil(p/k)*k):(v=g,w=p),m&&x&&n&&Rt((a-o)/n,k/1e3)?(M=Math.round(Math.min((a-o)/k,h)),k=(a-o)/M,v=o,w=a):b?(v=m?o:v,w=x?a:w,M=l-1,k=(w-v)/M):(M=(w-v)/k,M=Lt(M,Math.round(M),k/1e3)?Math.round(M):Math.ceil(M));const S=Math.max(Ft(k),Ft(v));y=Math.pow(10,$(r)?S:r),v=Math.round(v*y)/y,w=Math.round(w*y)/y;let P=0;for(m&&(d&&v!==o?(i.push({value:o}),v<o&&P++,Lt(Math.round((v+P*k)*y)/y,o,Ko(o,_,t))&&P++):v<o&&P++);P<M;++P)i.push({value:Math.round((v+P*k)*y)/y});return x&&d&&w!==a?i.length&&Lt(i[i.length-1].value,a,Ko(a,_,t))?i[i.length-1].value=a:i.push({value:a}):x&&w!==a||i.push({value:w}),i}({maxTicks:i,bounds:t.bounds,min:t.min,max:t.max,precision:e.precision,step:e.stepSize,count:e.count,maxDigits:this._maxDigits(),horizontal:this.isHorizontal(),minRotation:e.minRotation||0,includeBounds:!1!==e.includeBounds},this._range||this);return"ticks"===t.bounds&&Et(s,this,"value"),t.reverse?(s.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),s}configure(){const t=this.ticks;let e=this.min,i=this.max;if(super.configure(),this.options.offset&&t.length){const s=(i-e)/Math.max(t.length-1,1)/2;e-=s,i+=s}this._startValue=e,this._endValue=i,this._valueRange=i-e}getLabelForValue(t){return Ri(t,this.chart.options.locale,this.options.ticks.format)}}class Zo extends Go{determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=X(t)?t:0,this.max=X(e)?e:1,this.handleTickRangeOptions()}computeTickLimit(){const t=this.isHorizontal(),e=t?this.width:this.height,i=It(this.options.ticks.minRotation),s=(t?Math.sin(i):Math.cos(i))||.001,n=this._resolveTickFontOptions(0);return Math.ceil(e/Math.min(40,n.lineHeight/s))}getPixelForValue(t){return null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getValueForPixel(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange}}function Jo(t){return 1===t/Math.pow(10,Math.floor(Dt(t)))}Zo.id="linear",Zo.defaults={ticks:{callback:Os.formatters.numeric}};class Qo extends Bs{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._valueRange=0}parse(t,e){const i=Go.prototype.parse.apply(this,[t,e]);if(0!==i)return X(i)&&i>0?i:null;this._zero=!0}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=X(t)?Math.max(0,t):null,this.max=X(e)?Math.max(0,e):null,this.options.beginAtZero&&(this._zero=!0),this.handleTickRangeOptions()}handleTickRangeOptions(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let i=this.min,s=this.max;const n=e=>i=t?i:e,o=t=>s=e?s:t,a=(t,e)=>Math.pow(10,Math.floor(Dt(t))+e);i===s&&(i<=0?(n(1),o(10)):(n(a(i,-1)),o(a(s,1)))),i<=0&&n(a(s,-1)),s<=0&&o(a(i,1)),this._zero&&this.min!==this._suggestedMin&&i===a(this.min,0)&&n(a(i,-1)),this.min=i,this.max=s}buildTicks(){const t=this.options,e=function(t,e){const i=Math.floor(Dt(e.max)),s=Math.ceil(e.max/Math.pow(10,i)),n=[];let o=q(t.min,Math.pow(10,Math.floor(Dt(e.min)))),a=Math.floor(Dt(o)),r=Math.floor(o/Math.pow(10,a)),l=a<0?Math.pow(10,Math.abs(a)):1;do{n.push({value:o,major:Jo(o)}),++r,10===r&&(r=1,++a,l=a>=0?1:l),o=Math.round(r*Math.pow(10,a)*l)/l}while(a<i||a===i&&r<s);const h=q(t.max,o);return n.push({value:h,major:Jo(o)}),n}({min:this._userMin,max:this._userMax},this);return"ticks"===t.bounds&&Et(e,this,"value"),t.reverse?(e.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),e}getLabelForValue(t){return void 0===t?"0":Ri(t,this.chart.options.locale,this.options.ticks.format)}configure(){const t=this.min;super.configure(),this._startValue=Dt(t),this._valueRange=Dt(this.max)-Dt(t)}getPixelForValue(t){return void 0!==t&&0!==t||(t=this.min),null===t||isNaN(t)?NaN:this.getPixelForDecimal(t===this.min?0:(Dt(t)-this._startValue)/this._valueRange)}getValueForPixel(t){const e=this.getDecimalForPixel(t);return Math.pow(10,this._startValue+e*this._valueRange)}}function ta(t){const e=t.ticks;if(e.display&&t.display){const t=Ne(e.backdropPadding);return K(e.font&&e.font.size,bt.font.size)+t.height}return 0}function ea(t,e,i,s,n){return t===s||t===n?{start:e-i/2,end:e+i/2}:t<s||t>n?{start:e-i,end:e}:{start:e,end:e+i}}function ia(t){const e={l:t.left+t._padding.left,r:t.right-t._padding.right,t:t.top+t._padding.top,b:t.bottom-t._padding.bottom},i=Object.assign({},e),s=[],n=[],o=t._pointLabels.length,a=t.options.pointLabels,r=a.centerPointLabels?_t/o:0;for(let d=0;d<o;d++){const o=a.setContext(t.getPointLabelContext(d));n[d]=o.padding;const u=t.getPointPosition(d,t.drawingArea+n[d],r),f=He(o.font),g=(l=t.ctx,h=f,c=Y(c=t._pointLabels[d])?c:[c],{w:qt(l,h.string,c),h:c.length*h.lineHeight});s[d]=g;const p=Nt(t.getIndexAngle(d)+r),m=Math.round(zt(p));sa(i,e,p,ea(m,u.x,g.w,0,180),ea(m,u.y,g.h,90,270))}var l,h,c;t.setCenterPoint(e.l-i.l,i.r-e.r,e.t-i.t,i.b-e.b),t._pointLabelItems=function(t,e,i){const s=[],n=t._pointLabels.length,o=t.options,a=ta(o)/2,r=t.drawingArea,l=o.pointLabels.centerPointLabels?_t/n:0;for(let o=0;o<n;o++){const n=t.getPointPosition(o,r+a+i[o],l),h=Math.round(zt(Nt(n.angle+kt))),c=e[o],d=aa(n.y,c.h,h),u=na(h),f=oa(n.x,c.w,u);s.push({x:n.x,y:d,textAlign:u,left:f,top:d,right:f+c.w,bottom:d+c.h})}return s}(t,s,n)}function sa(t,e,i,s,n){const o=Math.abs(Math.sin(i)),a=Math.abs(Math.cos(i));let r=0,l=0;s.start<e.l?(r=(e.l-s.start)/o,t.l=Math.min(t.l,e.l-r)):s.end>e.r&&(r=(s.end-e.r)/o,t.r=Math.max(t.r,e.r+r)),n.start<e.t?(l=(e.t-n.start)/a,t.t=Math.min(t.t,e.t-l)):n.end>e.b&&(l=(n.end-e.b)/a,t.b=Math.max(t.b,e.b+l))}function na(t){return 0===t||180===t?"center":t<180?"left":"right"}function oa(t,e,i){return"right"===i?t-=e:"center"===i&&(t-=e/2),t}function aa(t,e,i){return 90===i||270===i?t-=e/2:(i>270||i<90)&&(t-=e),t}function ra(t,e,i,s){const{ctx:n}=t;if(i)n.arc(t.xCenter,t.yCenter,e,0,yt);else{let i=t.getPointPosition(0,e);n.moveTo(i.x,i.y);for(let o=1;o<s;o++)i=t.getPointPosition(o,e),n.lineTo(i.x,i.y)}}Qo.id="logarithmic",Qo.defaults={ticks:{callback:Os.formatters.logarithmic,major:{enabled:!0}}};class la extends Go{constructor(t){super(t),this.xCenter=void 0,this.yCenter=void 0,this.drawingArea=void 0,this._pointLabels=[],this._pointLabelItems=[]}setDimensions(){const t=this._padding=Ne(ta(this.options)/2),e=this.width=this.maxWidth-t.width,i=this.height=this.maxHeight-t.height;this.xCenter=Math.floor(this.left+e/2+t.left),this.yCenter=Math.floor(this.top+i/2+t.top),this.drawingArea=Math.floor(Math.min(e,i)/2)}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!1);this.min=X(t)&&!isNaN(t)?t:0,this.max=X(e)&&!isNaN(e)?e:0,this.handleTickRangeOptions()}computeTickLimit(){return Math.ceil(this.drawingArea/ta(this.options))}generateTickLabels(t){Go.prototype.generateTickLabels.call(this,t),this._pointLabels=this.getLabels().map(((t,e)=>{const i=J(this.options.pointLabels.callback,[t,e],this);return i||0===i?i:""})).filter(((t,e)=>this.chart.getDataVisibility(e)))}fit(){const t=this.options;t.display&&t.pointLabels.display?ia(this):this.setCenterPoint(0,0,0,0)}setCenterPoint(t,e,i,s){this.xCenter+=Math.floor((t-e)/2),this.yCenter+=Math.floor((i-s)/2),this.drawingArea-=Math.min(this.drawingArea/2,Math.max(t,e,i,s))}getIndexAngle(t){return Nt(t*(yt/(this._pointLabels.length||1))+It(this.options.startAngle||0))}getDistanceFromCenterForValue(t){if($(t))return NaN;const e=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*e:(t-this.min)*e}getValueForDistanceFromCenter(t){if($(t))return NaN;const e=t/(this.drawingArea/(this.max-this.min));return this.options.reverse?this.max-e:this.min+e}getPointLabelContext(t){const e=this._pointLabels||[];if(t>=0&&t<e.length){const i=e[t];return function(t,e,i){return Ye(t,{label:i,index:e,type:"pointLabel"})}(this.getContext(),t,i)}}getPointPosition(t,e,i=0){const s=this.getIndexAngle(t)-kt+i;return{x:Math.cos(s)*e+this.xCenter,y:Math.sin(s)*e+this.yCenter,angle:s}}getPointPositionForValue(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))}getBasePosition(t){return this.getPointPositionForValue(t||0,this.getBaseValue())}getPointLabelPosition(t){const{left:e,top:i,right:s,bottom:n}=this._pointLabelItems[t];return{left:e,top:i,right:s,bottom:n}}drawBackground(){const{backgroundColor:t,grid:{circular:e}}=this.options;if(t){const i=this.ctx;i.save(),i.beginPath(),ra(this,this.getDistanceFromCenterForValue(this._endValue),e,this._pointLabels.length),i.closePath(),i.fillStyle=t,i.fill(),i.restore()}}drawGrid(){const t=this.ctx,e=this.options,{angleLines:i,grid:s}=e,n=this._pointLabels.length;let o,a,r;if(e.pointLabels.display&&function(t,e){const{ctx:i,options:{pointLabels:s}}=t;for(let n=e-1;n>=0;n--){const e=s.setContext(t.getPointLabelContext(n)),o=He(e.font),{x:a,y:r,textAlign:l,left:h,top:c,right:d,bottom:u}=t._pointLabelItems[n],{backdropColor:f}=e;if(!$(f)){const t=Ne(e.backdropPadding);i.fillStyle=f,i.fillRect(h-t.left,c-t.top,d-h+t.width,u-c+t.height)}se(i,t._pointLabels[n],a,r+o.lineHeight/2,o,{color:e.color,textAlign:l,textBaseline:"middle"})}}(this,n),s.display&&this.ticks.forEach(((t,e)=>{if(0!==e){a=this.getDistanceFromCenterForValue(t.value);!function(t,e,i,s){const n=t.ctx,o=e.circular,{color:a,lineWidth:r}=e;!o&&!s||!a||!r||i<0||(n.save(),n.strokeStyle=a,n.lineWidth=r,n.setLineDash(e.borderDash),n.lineDashOffset=e.borderDashOffset,n.beginPath(),ra(t,i,o,s),n.closePath(),n.stroke(),n.restore())}(this,s.setContext(this.getContext(e-1)),a,n)}})),i.display){for(t.save(),o=n-1;o>=0;o--){const s=i.setContext(this.getPointLabelContext(o)),{color:n,lineWidth:l}=s;l&&n&&(t.lineWidth=l,t.strokeStyle=n,t.setLineDash(s.borderDash),t.lineDashOffset=s.borderDashOffset,a=this.getDistanceFromCenterForValue(e.ticks.reverse?this.min:this.max),r=this.getPointPosition(o,a),t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(r.x,r.y),t.stroke())}t.restore()}}drawBorder(){}drawLabels(){const t=this.ctx,e=this.options,i=e.ticks;if(!i.display)return;const s=this.getIndexAngle(0);let n,o;t.save(),t.translate(this.xCenter,this.yCenter),t.rotate(s),t.textAlign="center",t.textBaseline="middle",this.ticks.forEach(((s,a)=>{if(0===a&&!e.reverse)return;const r=i.setContext(this.getContext(a)),l=He(r.font);if(n=this.getDistanceFromCenterForValue(this.ticks[a].value),r.showLabelBackdrop){t.font=l.string,o=t.measureText(s.label).width,t.fillStyle=r.backdropColor;const e=Ne(r.backdropPadding);t.fillRect(-o/2-e.left,-n-l.size/2-e.top,o+e.width,l.size+e.height)}se(t,s.label,0,-n,l,{color:r.color})})),t.restore()}drawTitle(){}}la.id="radialLinear",la.defaults={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,lineWidth:1,borderDash:[],borderDashOffset:0},grid:{circular:!1},startAngle:0,ticks:{showLabelBackdrop:!0,callback:Os.formatters.numeric},pointLabels:{backdropColor:void 0,backdropPadding:2,display:!0,font:{size:10},callback:t=>t,padding:5,centerPointLabels:!1}},la.defaultRoutes={"angleLines.color":"borderColor","pointLabels.color":"color","ticks.color":"color"},la.descriptors={angleLines:{_fallback:"grid"}};const ha={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},ca=Object.keys(ha);function da(t,e){return t-e}function ua(t,e){if($(e))return null;const i=t._adapter,{parser:s,round:n,isoWeekday:o}=t._parseOpts;let a=e;return"function"==typeof s&&(a=s(a)),X(a)||(a="string"==typeof s?i.parse(a,s):i.parse(a)),null===a?null:(n&&(a="week"!==n||!Tt(o)&&!0!==o?i.startOf(a,n):i.startOf(a,"isoWeek",o)),+a)}function fa(t,e,i,s){const n=ca.length;for(let o=ca.indexOf(t);o<n-1;++o){const t=ha[ca[o]],n=t.steps?t.steps:Number.MAX_SAFE_INTEGER;if(t.common&&Math.ceil((i-e)/(n*t.size))<=s)return ca[o]}return ca[n-1]}function ga(t,e,i){if(i){if(i.length){const{lo:s,hi:n}=ae(i,e);t[i[s]>=e?i[s]:i[n]]=!0}}else t[e]=!0}function pa(t,e,i){const s=[],n={},o=e.length;let a,r;for(a=0;a<o;++a)r=e[a],n[r]=a,s.push({value:r,major:!1});return 0!==o&&i?function(t,e,i,s){const n=t._adapter,o=+n.startOf(e[0].value,s),a=e[e.length-1].value;let r,l;for(r=o;r<=a;r=+n.add(r,1,s))l=i[r],l>=0&&(e[l].major=!0);return e}(t,s,n,i):s}class ma extends Bs{constructor(t){super(t),this._cache={data:[],labels:[],all:[]},this._unit="day",this._majorUnit=void 0,this._offsets={},this._normalized=!1,this._parseOpts=void 0}init(t,e){const i=t.time||(t.time={}),s=this._adapter=new mn._date(t.adapters.date);ot(i.displayFormats,s.formats()),this._parseOpts={parser:i.parser,round:i.round,isoWeekday:i.isoWeekday},super.init(t),this._normalized=e.normalized}parse(t,e){return void 0===t?null:ua(this,t)}beforeLayout(){super.beforeLayout(),this._cache={data:[],labels:[],all:[]}}determineDataLimits(){const t=this.options,e=this._adapter,i=t.time.unit||"day";let{min:s,max:n,minDefined:o,maxDefined:a}=this.getUserBounds();function r(t){o||isNaN(t.min)||(s=Math.min(s,t.min)),a||isNaN(t.max)||(n=Math.max(n,t.max))}o&&a||(r(this._getLabelBounds()),"ticks"===t.bounds&&"labels"===t.ticks.source||r(this.getMinMax(!1))),s=X(s)&&!isNaN(s)?s:+e.startOf(Date.now(),i),n=X(n)&&!isNaN(n)?n:+e.endOf(Date.now(),i)+1,this.min=Math.min(s,n-1),this.max=Math.max(s+1,n)}_getLabelBounds(){const t=this.getLabelTimestamps();let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return t.length&&(e=t[0],i=t[t.length-1]),{min:e,max:i}}buildTicks(){const t=this.options,e=t.time,i=t.ticks,s="labels"===i.source?this.getLabelTimestamps():this._generate();"ticks"===t.bounds&&s.length&&(this.min=this._userMin||s[0],this.max=this._userMax||s[s.length-1]);const n=this.min,o=he(s,n,this.max);return this._unit=e.unit||(i.autoSkip?fa(e.minUnit,this.min,this.max,this._getLabelCapacity(n)):function(t,e,i,s,n){for(let o=ca.length-1;o>=ca.indexOf(i);o--){const i=ca[o];if(ha[i].common&&t._adapter.diff(n,s,i)>=e-1)return i}return ca[i?ca.indexOf(i):0]}(this,o.length,e.minUnit,this.min,this.max)),this._majorUnit=i.major.enabled&&"year"!==this._unit?function(t){for(let e=ca.indexOf(t)+1,i=ca.length;e<i;++e)if(ha[ca[e]].common)return ca[e]}(this._unit):void 0,this.initOffsets(s),t.reverse&&o.reverse(),pa(this,o,this._majorUnit)}initOffsets(t){let e,i,s=0,n=0;this.options.offset&&t.length&&(e=this.getDecimalForValue(t[0]),s=1===t.length?1-e:(this.getDecimalForValue(t[1])-e)/2,i=this.getDecimalForValue(t[t.length-1]),n=1===t.length?i:(i-this.getDecimalForValue(t[t.length-2]))/2);const o=t.length<3?.5:.25;s=jt(s,0,o),n=jt(n,0,o),this._offsets={start:s,end:n,factor:1/(s+1+n)}}_generate(){const t=this._adapter,e=this.min,i=this.max,s=this.options,n=s.time,o=n.unit||fa(n.minUnit,e,i,this._getLabelCapacity(e)),a=K(n.stepSize,1),r="week"===o&&n.isoWeekday,l=Tt(r)||!0===r,h={};let c,d,u=e;if(l&&(u=+t.startOf(u,"isoWeek",r)),u=+t.startOf(u,l?"day":o),t.diff(i,e,o)>1e5*a)throw new Error(e+" and "+i+" are too far apart with stepSize of "+a+" "+o);const f="data"===s.ticks.source&&this.getDataTimestamps();for(c=u,d=0;c<i;c=+t.add(c,a,o),d++)ga(h,c,f);return c!==i&&"ticks"!==s.bounds&&1!==d||ga(h,c,f),Object.keys(h).sort(((t,e)=>t-e)).map((t=>+t))}getLabelForValue(t){const e=this._adapter,i=this.options.time;return i.tooltipFormat?e.format(t,i.tooltipFormat):e.format(t,i.displayFormats.datetime)}_tickFormatFunction(t,e,i,s){const n=this.options,o=n.time.displayFormats,a=this._unit,r=this._majorUnit,l=a&&o[a],h=r&&o[r],c=i[e],d=r&&h&&c&&c.major,u=this._adapter.format(t,s||(d?h:l)),f=n.ticks.callback;return f?J(f,[u,e,i],this):u}generateTickLabels(t){let e,i,s;for(e=0,i=t.length;e<i;++e)s=t[e],s.label=this._tickFormatFunction(s.value,e,t)}getDecimalForValue(t){return null===t?NaN:(t-this.min)/(this.max-this.min)}getPixelForValue(t){const e=this._offsets,i=this.getDecimalForValue(t);return this.getPixelForDecimal((e.start+i)*e.factor)}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return this.min+i*(this.max-this.min)}_getLabelSize(t){const e=this.options.ticks,i=this.ctx.measureText(t).width,s=It(this.isHorizontal()?e.maxRotation:e.minRotation),n=Math.cos(s),o=Math.sin(s),a=this._resolveTickFontOptions(0).size;return{w:i*n+a*o,h:i*o+a*n}}_getLabelCapacity(t){const e=this.options.time,i=e.displayFormats,s=i[e.unit]||i.millisecond,n=this._tickFormatFunction(t,0,pa(this,[t],this._majorUnit),s),o=this._getLabelSize(n),a=Math.floor(this.isHorizontal()?this.width/o.w:this.height/o.h)-1;return a>0?a:1}getDataTimestamps(){let t,e,i=this._cache.data||[];if(i.length)return i;const s=this.getMatchingVisibleMetas();if(this._normalized&&s.length)return this._cache.data=s[0].controller.getAllParsedValues(this);for(t=0,e=s.length;t<e;++t)i=i.concat(s[t].controller.getAllParsedValues(this));return this._cache.data=this.normalize(i)}getLabelTimestamps(){const t=this._cache.labels||[];let e,i;if(t.length)return t;const s=this.getLabels();for(e=0,i=s.length;e<i;++e)t.push(ua(this,s[e]));return this._cache.labels=this._normalized?t:this.normalize(t)}normalize(t){return fe(t.sort(da))}}function xa(t,e,i){let s,n,o,a,r=0,l=t.length-1;i?(e>=t[r].pos&&e<=t[l].pos&&({lo:r,hi:l}=re(t,"pos",e)),({pos:s,time:o}=t[r]),({pos:n,time:a}=t[l])):(e>=t[r].time&&e<=t[l].time&&({lo:r,hi:l}=re(t,"time",e)),({time:s,pos:o}=t[r]),({time:n,pos:a}=t[l]));const h=n-s;return h?o+(a-o)*(e-s)/h:o}ma.id="time",ma.defaults={bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{source:"auto",major:{enabled:!1}}};class ba extends ma{constructor(t){super(t),this._table=[],this._minPos=void 0,this._tableRange=void 0}initOffsets(){const t=this._getTimestampsForTable(),e=this._table=this.buildLookupTable(t);this._minPos=xa(e,this.min),this._tableRange=xa(e,this.max)-this._minPos,super.initOffsets(t)}buildLookupTable(t){const{min:e,max:i}=this,s=[],n=[];let o,a,r,l,h;for(o=0,a=t.length;o<a;++o)l=t[o],l>=e&&l<=i&&s.push(l);if(s.length<2)return[{time:e,pos:0},{time:i,pos:1}];for(o=0,a=s.length;o<a;++o)h=s[o+1],r=s[o-1],l=s[o],Math.round((h+r)/2)!==l&&n.push({time:l,pos:o/(a-1)});return n}_getTimestampsForTable(){let t=this._cache.all||[];if(t.length)return t;const e=this.getDataTimestamps(),i=this.getLabelTimestamps();return t=e.length&&i.length?this.normalize(e.concat(i)):e.length?e:i,t=this._cache.all=t,t}getDecimalForValue(t){return(xa(this._table,t)-this._minPos)/this._tableRange}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return xa(this._table,i*this._tableRange+this._minPos,!0)}}ba.id="timeseries",ba.defaults=ma.defaults;var _a=Object.freeze({__proto__:null,CategoryScale:qo,LinearScale:Zo,LogarithmicScale:Qo,RadialLinearScale:la,TimeScale:ma,TimeSeriesScale:ba});return dn.register(Rn,_a,no,Uo),dn.helpers={...Yi},dn._adapters=mn,dn.Animation=us,dn.Animations=gs,dn.animator=a,dn.controllers=Ws.controllers.items,dn.DatasetController=Ps,dn.Element=Ds,dn.elements=no,dn.Interaction=Ee,dn.layouts=ni,dn.platforms=hs,dn.Scale=Bs,dn.Ticks=Os,Object.assign(dn,Rn,_a,no,Uo,hs),dn.Chart=dn,"undefined"!=typeof window&&(window.Chart=dn),dn}));
1
  /*!
2
+ * Chart.js v3.8.0
3
  * https://www.chartjs.org
4
+ * (c) 2022 Chart.js Contributors
5
  * Released under the MIT License
6
  */
7
  !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";const t="undefined"==typeof window?function(t){return t()}:window.requestAnimationFrame;function e(e,i,s){const n=s||(t=>Array.prototype.slice.call(t));let o=!1,a=[];return function(...s){a=n(s),o||(o=!0,t.call(window,(()=>{o=!1,e.apply(i,a)})))}}function i(t,e){let i;return function(...s){return e?(clearTimeout(i),i=setTimeout(t,e,s)):t.apply(this,s),e}}const s=t=>"start"===t?"left":"end"===t?"right":"center",n=(t,e,i)=>"start"===t?e:"end"===t?i:(e+i)/2,o=(t,e,i,s)=>t===(s?"left":"right")?i:"center"===t?(e+i)/2:e;var a=new class{constructor(){this._request=null,this._charts=new Map,this._running=!1,this._lastDate=void 0}_notify(t,e,i,s){const n=e.listeners[s],o=e.duration;n.forEach((s=>s({chart:t,initial:e.initial,numSteps:o,currentStep:Math.min(i-e.start,o)})))}_refresh(){this._request||(this._running=!0,this._request=t.call(window,(()=>{this._update(),this._request=null,this._running&&this._refresh()})))}_update(t=Date.now()){let e=0;this._charts.forEach(((i,s)=>{if(!i.running||!i.items.length)return;const n=i.items;let o,a=n.length-1,r=!1;for(;a>=0;--a)o=n[a],o._active?(o._total>i.duration&&(i.duration=o._total),o.tick(t),r=!0):(n[a]=n[n.length-1],n.pop());r&&(s.draw(),this._notify(s,i,t,"progress")),n.length||(i.running=!1,this._notify(s,i,t,"complete"),i.initial=!1),e+=n.length})),this._lastDate=t,0===e&&(this._running=!1)}_getAnims(t){const e=this._charts;let i=e.get(t);return i||(i={running:!1,initial:!0,items:[],listeners:{complete:[],progress:[]}},e.set(t,i)),i}listen(t,e,i){this._getAnims(t).listeners[e].push(i)}add(t,e){e&&e.length&&this._getAnims(t).items.push(...e)}has(t){return this._getAnims(t).items.length>0}start(t){const e=this._charts.get(t);e&&(e.running=!0,e.start=Date.now(),e.duration=e.items.reduce(((t,e)=>Math.max(t,e._duration)),0),this._refresh())}running(t){if(!this._running)return!1;const e=this._charts.get(t);return!!(e&&e.running&&e.items.length)}stop(t){const e=this._charts.get(t);if(!e||!e.items.length)return;const i=e.items;let s=i.length-1;for(;s>=0;--s)i[s].cancel();e.items=[],this._notify(t,e,Date.now(),"complete")}remove(t){return this._charts.delete(t)}};
8
  /*!
9
+ * @kurkle/color v0.2.1
10
  * https://github.com/kurkle/color#readme
11
+ * (c) 2022 Jukka Kurkela
12
  * Released under the MIT License
13
+ */function r(t){return t+.5|0}const l=(t,e,i)=>Math.max(Math.min(t,i),e);function h(t){return l(r(2.55*t),0,255)}function c(t){return l(r(255*t),0,255)}function d(t){return l(r(t/2.55)/100,0,1)}function u(t){return l(r(100*t),0,100)}const f={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},g=[..."0123456789ABCDEF"],p=t=>g[15&t],m=t=>g[(240&t)>>4]+g[15&t],b=t=>(240&t)>>4==(15&t);function x(t){var e=(t=>b(t.r)&&b(t.g)&&b(t.b)&&b(t.a))(t)?p:m;return t?"#"+e(t.r)+e(t.g)+e(t.b)+((t,e)=>t<255?e(t):"")(t.a,e):void 0}const _=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function y(t,e,i){const s=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-s*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function v(t,e,i){const s=(s,n=(s+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[s(5),s(3),s(1)]}function w(t,e,i){const s=y(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)s[n]*=1-e-i,s[n]+=e;return s}function M(t){const e=t.r/255,i=t.g/255,s=t.b/255,n=Math.max(e,i,s),o=Math.min(e,i,s),a=(n+o)/2;let r,l,h;return n!==o&&(h=n-o,l=a>.5?h/(2-n-o):h/(n+o),r=function(t,e,i,s,n){return t===n?(e-i)/s+(e<i?6:0):e===n?(i-t)/s+2:(t-e)/s+4}(e,i,s,h,n),r=60*r+.5),[0|r,l||0,a]}function k(t,e,i,s){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,s)).map(c)}function S(t,e,i){return k(y,t,e,i)}function P(t){return(t%360+360)%360}function D(t){const e=_.exec(t);let i,s=255;if(!e)return;e[5]!==i&&(s=e[6]?h(+e[5]):c(+e[5]));const n=P(+e[2]),o=+e[3]/100,a=+e[4]/100;return i="hwb"===e[1]?function(t,e,i){return k(w,t,e,i)}(n,o,a):"hsv"===e[1]?function(t,e,i){return k(v,t,e,i)}(n,o,a):S(n,o,a),{r:i[0],g:i[1],b:i[2],a:s}}const C={x:"dark",Z:"light",Y:"re",X:"blu",W:"gr",V:"medium",U:"slate",A:"ee",T:"ol",S:"or",B:"ra",C:"lateg",D:"ights",R:"in",Q:"turquois",E:"hi",P:"ro",O:"al",N:"le",M:"de",L:"yello",F:"en",K:"ch",G:"arks",H:"ea",I:"ightg",J:"wh"},O={OiceXe:"f0f8ff",antiquewEte:"faebd7",aqua:"ffff",aquamarRe:"7fffd4",azuY:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"0",blanKedOmond:"ffebcd",Xe:"ff",XeviTet:"8a2be2",bPwn:"a52a2a",burlywood:"deb887",caMtXe:"5f9ea0",KartYuse:"7fff00",KocTate:"d2691e",cSO:"ff7f50",cSnflowerXe:"6495ed",cSnsilk:"fff8dc",crimson:"dc143c",cyan:"ffff",xXe:"8b",xcyan:"8b8b",xgTMnPd:"b8860b",xWay:"a9a9a9",xgYF:"6400",xgYy:"a9a9a9",xkhaki:"bdb76b",xmagFta:"8b008b",xTivegYF:"556b2f",xSange:"ff8c00",xScEd:"9932cc",xYd:"8b0000",xsOmon:"e9967a",xsHgYF:"8fbc8f",xUXe:"483d8b",xUWay:"2f4f4f",xUgYy:"2f4f4f",xQe:"ced1",xviTet:"9400d3",dAppRk:"ff1493",dApskyXe:"bfff",dimWay:"696969",dimgYy:"696969",dodgerXe:"1e90ff",fiYbrick:"b22222",flSOwEte:"fffaf0",foYstWAn:"228b22",fuKsia:"ff00ff",gaRsbSo:"dcdcdc",ghostwEte:"f8f8ff",gTd:"ffd700",gTMnPd:"daa520",Way:"808080",gYF:"8000",gYFLw:"adff2f",gYy:"808080",honeyMw:"f0fff0",hotpRk:"ff69b4",RdianYd:"cd5c5c",Rdigo:"4b0082",ivSy:"fffff0",khaki:"f0e68c",lavFMr:"e6e6fa",lavFMrXsh:"fff0f5",lawngYF:"7cfc00",NmoncEffon:"fffacd",ZXe:"add8e6",ZcSO:"f08080",Zcyan:"e0ffff",ZgTMnPdLw:"fafad2",ZWay:"d3d3d3",ZgYF:"90ee90",ZgYy:"d3d3d3",ZpRk:"ffb6c1",ZsOmon:"ffa07a",ZsHgYF:"20b2aa",ZskyXe:"87cefa",ZUWay:"778899",ZUgYy:"778899",ZstAlXe:"b0c4de",ZLw:"ffffe0",lime:"ff00",limegYF:"32cd32",lRF:"faf0e6",magFta:"ff00ff",maPon:"800000",VaquamarRe:"66cdaa",VXe:"cd",VScEd:"ba55d3",VpurpN:"9370db",VsHgYF:"3cb371",VUXe:"7b68ee",VsprRggYF:"fa9a",VQe:"48d1cc",VviTetYd:"c71585",midnightXe:"191970",mRtcYam:"f5fffa",mistyPse:"ffe4e1",moccasR:"ffe4b5",navajowEte:"ffdead",navy:"80",Tdlace:"fdf5e6",Tive:"808000",TivedBb:"6b8e23",Sange:"ffa500",SangeYd:"ff4500",ScEd:"da70d6",pOegTMnPd:"eee8aa",pOegYF:"98fb98",pOeQe:"afeeee",pOeviTetYd:"db7093",papayawEp:"ffefd5",pHKpuff:"ffdab9",peru:"cd853f",pRk:"ffc0cb",plum:"dda0dd",powMrXe:"b0e0e6",purpN:"800080",YbeccapurpN:"663399",Yd:"ff0000",Psybrown:"bc8f8f",PyOXe:"4169e1",saddNbPwn:"8b4513",sOmon:"fa8072",sandybPwn:"f4a460",sHgYF:"2e8b57",sHshell:"fff5ee",siFna:"a0522d",silver:"c0c0c0",skyXe:"87ceeb",UXe:"6a5acd",UWay:"708090",UgYy:"708090",snow:"fffafa",sprRggYF:"ff7f",stAlXe:"4682b4",tan:"d2b48c",teO:"8080",tEstN:"d8bfd8",tomato:"ff6347",Qe:"40e0d0",viTet:"ee82ee",JHt:"f5deb3",wEte:"ffffff",wEtesmoke:"f5f5f5",Lw:"ffff00",LwgYF:"9acd32"};let A;function T(t){A||(A=function(){const t={},e=Object.keys(O),i=Object.keys(C);let s,n,o,a,r;for(s=0;s<e.length;s++){for(a=r=e[s],n=0;n<i.length;n++)o=i[n],r=r.replace(o,C[o]);o=parseInt(O[a],16),t[r]=[o>>16&255,o>>8&255,255&o]}return t}(),A.transparent=[0,0,0,0]);const e=A[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}const L=/^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;const R=t=>t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055,E=t=>t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4);function I(t,e,i){if(t){let s=M(t);s[e]=Math.max(0,Math.min(s[e]+s[e]*i,0===e?360:1)),s=S(s),t.r=s[0],t.g=s[1],t.b=s[2]}}function z(t,e){return t?Object.assign(e||{},t):t}function F(t){var e={r:0,g:0,b:0,a:255};return Array.isArray(t)?t.length>=3&&(e={r:t[0],g:t[1],b:t[2],a:255},t.length>3&&(e.a=c(t[3]))):(e=z(t,{r:0,g:0,b:0,a:1})).a=c(e.a),e}function B(t){return"r"===t.charAt(0)?function(t){const e=L.exec(t);let i,s,n,o=255;if(e){if(e[7]!==i){const t=+e[7];o=e[8]?h(t):l(255*t,0,255)}return i=+e[1],s=+e[3],n=+e[5],i=255&(e[2]?h(i):l(i,0,255)),s=255&(e[4]?h(s):l(s,0,255)),n=255&(e[6]?h(n):l(n,0,255)),{r:i,g:s,b:n,a:o}}}(t):D(t)}class V{constructor(t){if(t instanceof V)return t;const e=typeof t;let i;var s,n,o;"object"===e?i=F(t):"string"===e&&(o=(s=t).length,"#"===s[0]&&(4===o||5===o?n={r:255&17*f[s[1]],g:255&17*f[s[2]],b:255&17*f[s[3]],a:5===o?17*f[s[4]]:255}:7!==o&&9!==o||(n={r:f[s[1]]<<4|f[s[2]],g:f[s[3]]<<4|f[s[4]],b:f[s[5]]<<4|f[s[6]],a:9===o?f[s[7]]<<4|f[s[8]]:255})),i=n||T(t)||B(t)),this._rgb=i,this._valid=!!i}get valid(){return this._valid}get rgb(){var t=z(this._rgb);return t&&(t.a=d(t.a)),t}set rgb(t){this._rgb=F(t)}rgbString(){return this._valid?(t=this._rgb)&&(t.a<255?`rgba(${t.r}, ${t.g}, ${t.b}, ${d(t.a)})`:`rgb(${t.r}, ${t.g}, ${t.b})`):void 0;var t}hexString(){return this._valid?x(this._rgb):void 0}hslString(){return this._valid?function(t){if(!t)return;const e=M(t),i=e[0],s=u(e[1]),n=u(e[2]);return t.a<255?`hsla(${i}, ${s}%, ${n}%, ${d(t.a)})`:`hsl(${i}, ${s}%, ${n}%)`}(this._rgb):void 0}mix(t,e){if(t){const i=this.rgb,s=t.rgb;let n;const o=e===n?.5:e,a=2*o-1,r=i.a-s.a,l=((a*r==-1?a:(a+r)/(1+a*r))+1)/2;n=1-l,i.r=255&l*i.r+n*s.r+.5,i.g=255&l*i.g+n*s.g+.5,i.b=255&l*i.b+n*s.b+.5,i.a=o*i.a+(1-o)*s.a,this.rgb=i}return this}interpolate(t,e){return t&&(this._rgb=function(t,e,i){const s=E(d(t.r)),n=E(d(t.g)),o=E(d(t.b));return{r:c(R(s+i*(E(d(e.r))-s))),g:c(R(n+i*(E(d(e.g))-n))),b:c(R(o+i*(E(d(e.b))-o))),a:t.a+i*(e.a-t.a)}}(this._rgb,t._rgb,e)),this}clone(){return new V(this.rgb)}alpha(t){return this._rgb.a=c(t),this}clearer(t){return this._rgb.a*=1-t,this}greyscale(){const t=this._rgb,e=r(.3*t.r+.59*t.g+.11*t.b);return t.r=t.g=t.b=e,this}opaquer(t){return this._rgb.a*=1+t,this}negate(){const t=this._rgb;return t.r=255-t.r,t.g=255-t.g,t.b=255-t.b,this}lighten(t){return I(this._rgb,2,t),this}darken(t){return I(this._rgb,2,-t),this}saturate(t){return I(this._rgb,1,t),this}desaturate(t){return I(this._rgb,1,-t),this}rotate(t){return function(t,e){var i=M(t);i[0]=P(i[0]+e),i=S(i),t.r=i[0],t.g=i[1],t.b=i[2]}(this._rgb,t),this}}function N(t){return new V(t)}function W(t){if(t&&"object"==typeof t){const e=t.toString();return"[object CanvasPattern]"===e||"[object CanvasGradient]"===e}return!1}function H(t){return W(t)?t:N(t)}function j(t){return W(t)?t:N(t).saturate(.5).darken(.1).hexString()}function $(){}const Y=function(){let t=0;return function(){return t++}}();function U(t){return null==t}function X(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.slice(0,7)&&"Array]"===e.slice(-6)}function q(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}const K=t=>("number"==typeof t||t instanceof Number)&&isFinite(+t);function G(t,e){return K(t)?t:e}function Z(t,e){return void 0===t?e:t}const J=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:t/e,Q=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function tt(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function et(t,e,i,s){let n,o,a;if(X(t))if(o=t.length,s)for(n=o-1;n>=0;n--)e.call(i,t[n],n);else for(n=0;n<o;n++)e.call(i,t[n],n);else if(q(t))for(a=Object.keys(t),o=a.length,n=0;n<o;n++)e.call(i,t[a[n]],a[n])}function it(t,e){let i,s,n,o;if(!t||!e||t.length!==e.length)return!1;for(i=0,s=t.length;i<s;++i)if(n=t[i],o=e[i],n.datasetIndex!==o.datasetIndex||n.index!==o.index)return!1;return!0}function st(t){if(X(t))return t.map(st);if(q(t)){const e=Object.create(null),i=Object.keys(t),s=i.length;let n=0;for(;n<s;++n)e[i[n]]=st(t[i[n]]);return e}return t}function nt(t){return-1===["__proto__","prototype","constructor"].indexOf(t)}function ot(t,e,i,s){if(!nt(t))return;const n=e[t],o=i[t];q(n)&&q(o)?at(n,o,s):e[t]=st(o)}function at(t,e,i){const s=X(e)?e:[e],n=s.length;if(!q(t))return t;const o=(i=i||{}).merger||ot;for(let a=0;a<n;++a){if(!q(e=s[a]))continue;const n=Object.keys(e);for(let s=0,a=n.length;s<a;++s)o(n[s],t,e,i)}return t}function rt(t,e){return at(t,e,{merger:lt})}function lt(t,e,i){if(!nt(t))return;const s=e[t],n=i[t];q(s)&&q(n)?rt(s,n):Object.prototype.hasOwnProperty.call(e,t)||(e[t]=st(n))}function ht(t,e){const i=t.indexOf(".",e);return-1===i?t.length:i}function ct(t,e){if(""===e)return t;let i=0,s=ht(e,i);for(;t&&s>i;)t=t[e.slice(i,s)],i=s+1,s=ht(e,i);return t}function dt(t){return t.charAt(0).toUpperCase()+t.slice(1)}const ut=t=>void 0!==t,ft=t=>"function"==typeof t,gt=(t,e)=>{if(t.size!==e.size)return!1;for(const i of t)if(!e.has(i))return!1;return!0};function pt(t){return"mouseup"===t.type||"click"===t.type||"contextmenu"===t.type}const mt=Object.create(null),bt=Object.create(null);function xt(t,e){if(!e)return t;const i=e.split(".");for(let e=0,s=i.length;e<s;++e){const s=i[e];t=t[s]||(t[s]=Object.create(null))}return t}function _t(t,e,i){return"string"==typeof e?at(xt(t,e),i):at(xt(t,""),e)}var yt=new class{constructor(t){this.animation=void 0,this.backgroundColor="rgba(0,0,0,0.1)",this.borderColor="rgba(0,0,0,0.1)",this.color="#666",this.datasets={},this.devicePixelRatio=t=>t.chart.platform.getDevicePixelRatio(),this.elements={},this.events=["mousemove","mouseout","click","touchstart","touchmove"],this.font={family:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",size:12,style:"normal",lineHeight:1.2,weight:null},this.hover={},this.hoverBackgroundColor=(t,e)=>j(e.backgroundColor),this.hoverBorderColor=(t,e)=>j(e.borderColor),this.hoverColor=(t,e)=>j(e.color),this.indexAxis="x",this.interaction={mode:"nearest",intersect:!0,includeInvisible:!1},this.maintainAspectRatio=!0,this.onHover=null,this.onClick=null,this.parsing=!0,this.plugins={},this.responsive=!0,this.scale=void 0,this.scales={},this.showLine=!0,this.drawActiveElementsOnTop=!0,this.describe(t)}set(t,e){return _t(this,t,e)}get(t){return xt(this,t)}describe(t,e){return _t(bt,t,e)}override(t,e){return _t(mt,t,e)}route(t,e,i,s){const n=xt(this,t),o=xt(this,i),a="_"+e;Object.defineProperties(n,{[a]:{value:n[e],writable:!0},[e]:{enumerable:!0,get(){const t=this[a],e=o[s];return q(t)?Object.assign({},e,t):Z(t,e)},set(t){this[a]=t}}})}}({_scriptable:t=>!t.startsWith("on"),_indexable:t=>"events"!==t,hover:{_fallback:"interaction"},interaction:{_scriptable:!1,_indexable:!1}});function vt(t,e,i){i=i||(i=>t[i]<e);let s,n=t.length-1,o=0;for(;n-o>1;)s=o+n>>1,i(s)?o=s:n=s;return{lo:o,hi:n}}const wt=(t,e,i)=>vt(t,i,(s=>t[s][e]<i)),Mt=(t,e,i)=>vt(t,i,(s=>t[s][e]>=i));function kt(t,e,i){let s=0,n=t.length;for(;s<n&&t[s]<e;)s++;for(;n>s&&t[n-1]>i;)n--;return s>0||n<t.length?t.slice(s,n):t}const St=["push","pop","shift","splice","unshift"];function Pt(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),St.forEach((e=>{const i="_onData"+dt(e),s=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const n=s.apply(this,e);return t._chartjs.listeners.forEach((t=>{"function"==typeof t[i]&&t[i](...e)})),n}})})))}function Dt(t,e){const i=t._chartjs;if(!i)return;const s=i.listeners,n=s.indexOf(e);-1!==n&&s.splice(n,1),s.length>0||(St.forEach((e=>{delete t[e]})),delete t._chartjs)}function Ct(t){const e=new Set;let i,s;for(i=0,s=t.length;i<s;++i)e.add(t[i]);return e.size===s?t:Array.from(e)}const Ot=Math.PI,At=2*Ot,Tt=At+Ot,Lt=Number.POSITIVE_INFINITY,Rt=Ot/180,Et=Ot/2,It=Ot/4,zt=2*Ot/3,Ft=Math.log10,Bt=Math.sign;function Vt(t){const e=Math.round(t);t=Ht(t,e,t/1e3)?e:t;const i=Math.pow(10,Math.floor(Ft(t))),s=t/i;return(s<=1?1:s<=2?2:s<=5?5:10)*i}function Nt(t){const e=[],i=Math.sqrt(t);let s;for(s=1;s<i;s++)t%s==0&&(e.push(s),e.push(t/s));return i===(0|i)&&e.push(i),e.sort(((t,e)=>t-e)).pop(),e}function Wt(t){return!isNaN(parseFloat(t))&&isFinite(t)}function Ht(t,e,i){return Math.abs(t-e)<i}function jt(t,e){const i=Math.round(t);return i-e<=t&&i+e>=t}function $t(t,e,i){let s,n,o;for(s=0,n=t.length;s<n;s++)o=t[s][i],isNaN(o)||(e.min=Math.min(e.min,o),e.max=Math.max(e.max,o))}function Yt(t){return t*(Ot/180)}function Ut(t){return t*(180/Ot)}function Xt(t){if(!K(t))return;let e=1,i=0;for(;Math.round(t*e)/e!==t;)e*=10,i++;return i}function qt(t,e){const i=e.x-t.x,s=e.y-t.y,n=Math.sqrt(i*i+s*s);let o=Math.atan2(s,i);return o<-.5*Ot&&(o+=At),{angle:o,distance:n}}function Kt(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function Gt(t,e){return(t-e+Tt)%At-Ot}function Zt(t){return(t%At+At)%At}function Jt(t,e,i,s){const n=Zt(t),o=Zt(e),a=Zt(i),r=Zt(o-n),l=Zt(a-n),h=Zt(n-o),c=Zt(n-a);return n===o||n===a||s&&o===a||r>l&&h<c}function Qt(t,e,i){return Math.max(e,Math.min(i,t))}function te(t){return Qt(t,-32768,32767)}function ee(t,e,i,s=1e-6){return t>=Math.min(e,i)-s&&t<=Math.max(e,i)+s}function ie(){return"undefined"!=typeof window&&"undefined"!=typeof document}function se(t){let e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e}function ne(t,e,i){let s;return"string"==typeof t?(s=parseInt(t,10),-1!==t.indexOf("%")&&(s=s/100*e.parentNode[i])):s=t,s}const oe=t=>window.getComputedStyle(t,null);function ae(t,e){return oe(t).getPropertyValue(e)}const re=["top","right","bottom","left"];function le(t,e,i){const s={};i=i?"-"+i:"";for(let n=0;n<4;n++){const o=re[n];s[o]=parseFloat(t[e+"-"+o+i])||0}return s.width=s.left+s.right,s.height=s.top+s.bottom,s}function he(t,e){if("native"in t)return t;const{canvas:i,currentDevicePixelRatio:s}=e,n=oe(i),o="border-box"===n.boxSizing,a=le(n,"padding"),r=le(n,"border","width"),{x:l,y:h,box:c}=function(t,e){const i=t.touches,s=i&&i.length?i[0]:t,{offsetX:n,offsetY:o}=s;let a,r,l=!1;if(((t,e,i)=>(t>0||e>0)&&(!i||!i.shadowRoot))(n,o,t.target))a=n,r=o;else{const t=e.getBoundingClientRect();a=s.clientX-t.left,r=s.clientY-t.top,l=!0}return{x:a,y:r,box:l}}(t,i),d=a.left+(c&&r.left),u=a.top+(c&&r.top);let{width:f,height:g}=e;return o&&(f-=a.width+r.width,g-=a.height+r.height),{x:Math.round((l-d)/f*i.width/s),y:Math.round((h-u)/g*i.height/s)}}const ce=t=>Math.round(10*t)/10;function de(t,e,i,s){const n=oe(t),o=le(n,"margin"),a=ne(n.maxWidth,t,"clientWidth")||Lt,r=ne(n.maxHeight,t,"clientHeight")||Lt,l=function(t,e,i){let s,n;if(void 0===e||void 0===i){const o=se(t);if(o){const t=o.getBoundingClientRect(),a=oe(o),r=le(a,"border","width"),l=le(a,"padding");e=t.width-l.width-r.width,i=t.height-l.height-r.height,s=ne(a.maxWidth,o,"clientWidth"),n=ne(a.maxHeight,o,"clientHeight")}else e=t.clientWidth,i=t.clientHeight}return{width:e,height:i,maxWidth:s||Lt,maxHeight:n||Lt}}(t,e,i);let{width:h,height:c}=l;if("content-box"===n.boxSizing){const t=le(n,"border","width"),e=le(n,"padding");h-=e.width+t.width,c-=e.height+t.height}return h=Math.max(0,h-o.width),c=Math.max(0,s?Math.floor(h/s):c-o.height),h=ce(Math.min(h,a,l.maxWidth)),c=ce(Math.min(c,r,l.maxHeight)),h&&!c&&(c=ce(h/2)),{width:h,height:c}}function ue(t,e,i){const s=e||1,n=Math.floor(t.height*s),o=Math.floor(t.width*s);t.height=n/s,t.width=o/s;const a=t.canvas;return a.style&&(i||!a.style.height&&!a.style.width)&&(a.style.height=`${t.height}px`,a.style.width=`${t.width}px`),(t.currentDevicePixelRatio!==s||a.height!==n||a.width!==o)&&(t.currentDevicePixelRatio=s,a.height=n,a.width=o,t.ctx.setTransform(s,0,0,s,0,0),!0)}const fe=function(){let t=!1;try{const e={get passive(){return t=!0,!1}};window.addEventListener("test",null,e),window.removeEventListener("test",null,e)}catch(t){}return t}();function ge(t,e){const i=ae(t,e),s=i&&i.match(/^(\d+)(\.\d+)?px$/);return s?+s[1]:void 0}function pe(t){return!t||U(t.size)||U(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family}function me(t,e,i,s,n){let o=e[n];return o||(o=e[n]=t.measureText(n).width,i.push(n)),o>s&&(s=o),s}function be(t,e,i,s){let n=(s=s||{}).data=s.data||{},o=s.garbageCollect=s.garbageCollect||[];s.font!==e&&(n=s.data={},o=s.garbageCollect=[],s.font=e),t.save(),t.font=e;let a=0;const r=i.length;let l,h,c,d,u;for(l=0;l<r;l++)if(d=i[l],null!=d&&!0!==X(d))a=me(t,n,o,a,d);else if(X(d))for(h=0,c=d.length;h<c;h++)u=d[h],null==u||X(u)||(a=me(t,n,o,a,u));t.restore();const f=o.length/2;if(f>i.length){for(l=0;l<f;l++)delete n[o[l]];o.splice(0,f)}return a}function xe(t,e,i){const s=t.currentDevicePixelRatio,n=0!==i?Math.max(i/2,.5):0;return Math.round((e-n)*s)/s+n}function _e(t,e){(e=e||t.getContext("2d")).save(),e.resetTransform(),e.clearRect(0,0,t.width,t.height),e.restore()}function ye(t,e,i,s){let n,o,a,r,l;const h=e.pointStyle,c=e.rotation,d=e.radius;let u=(c||0)*Rt;if(h&&"object"==typeof h&&(n=h.toString(),"[object HTMLImageElement]"===n||"[object HTMLCanvasElement]"===n))return t.save(),t.translate(i,s),t.rotate(u),t.drawImage(h,-h.width/2,-h.height/2,h.width,h.height),void t.restore();if(!(isNaN(d)||d<=0)){switch(t.beginPath(),h){default:t.arc(i,s,d,0,At),t.closePath();break;case"triangle":t.moveTo(i+Math.sin(u)*d,s-Math.cos(u)*d),u+=zt,t.lineTo(i+Math.sin(u)*d,s-Math.cos(u)*d),u+=zt,t.lineTo(i+Math.sin(u)*d,s-Math.cos(u)*d),t.closePath();break;case"rectRounded":l=.516*d,r=d-l,o=Math.cos(u+It)*r,a=Math.sin(u+It)*r,t.arc(i-o,s-a,l,u-Ot,u-Et),t.arc(i+a,s-o,l,u-Et,u),t.arc(i+o,s+a,l,u,u+Et),t.arc(i-a,s+o,l,u+Et,u+Ot),t.closePath();break;case"rect":if(!c){r=Math.SQRT1_2*d,t.rect(i-r,s-r,2*r,2*r);break}u+=It;case"rectRot":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+a,s-o),t.lineTo(i+o,s+a),t.lineTo(i-a,s+o),t.closePath();break;case"crossRot":u+=It;case"cross":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o);break;case"star":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o),u+=It,o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o);break;case"line":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a);break;case"dash":t.moveTo(i,s),t.lineTo(i+Math.cos(u)*d,s+Math.sin(u)*d)}t.fill(),e.borderWidth>0&&t.stroke()}}function ve(t,e,i){return i=i||.5,!e||t&&t.x>e.left-i&&t.x<e.right+i&&t.y>e.top-i&&t.y<e.bottom+i}function we(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()}function Me(t){t.restore()}function ke(t,e,i,s,n){if(!e)return t.lineTo(i.x,i.y);if("middle"===n){const s=(e.x+i.x)/2;t.lineTo(s,e.y),t.lineTo(s,i.y)}else"after"===n!=!!s?t.lineTo(e.x,i.y):t.lineTo(i.x,e.y);t.lineTo(i.x,i.y)}function Se(t,e,i,s){if(!e)return t.lineTo(i.x,i.y);t.bezierCurveTo(s?e.cp1x:e.cp2x,s?e.cp1y:e.cp2y,s?i.cp2x:i.cp1x,s?i.cp2y:i.cp1y,i.x,i.y)}function Pe(t,e,i,s,n,o={}){const a=X(e)?e:[e],r=o.strokeWidth>0&&""!==o.strokeColor;let l,h;for(t.save(),t.font=n.string,function(t,e){e.translation&&t.translate(e.translation[0],e.translation[1]);U(e.rotation)||t.rotate(e.rotation);e.color&&(t.fillStyle=e.color);e.textAlign&&(t.textAlign=e.textAlign);e.textBaseline&&(t.textBaseline=e.textBaseline)}(t,o),l=0;l<a.length;++l)h=a[l],r&&(o.strokeColor&&(t.strokeStyle=o.strokeColor),U(o.strokeWidth)||(t.lineWidth=o.strokeWidth),t.strokeText(h,i,s,o.maxWidth)),t.fillText(h,i,s,o.maxWidth),De(t,i,s,h,o),s+=n.lineHeight;t.restore()}function De(t,e,i,s,n){if(n.strikethrough||n.underline){const o=t.measureText(s),a=e-o.actualBoundingBoxLeft,r=e+o.actualBoundingBoxRight,l=i-o.actualBoundingBoxAscent,h=i+o.actualBoundingBoxDescent,c=n.strikethrough?(l+h)/2:h;t.strokeStyle=t.fillStyle,t.beginPath(),t.lineWidth=n.decorationWidth||2,t.moveTo(a,c),t.lineTo(r,c),t.stroke()}}function Ce(t,e){const{x:i,y:s,w:n,h:o,radius:a}=e;t.arc(i+a.topLeft,s+a.topLeft,a.topLeft,-Et,Ot,!0),t.lineTo(i,s+o-a.bottomLeft),t.arc(i+a.bottomLeft,s+o-a.bottomLeft,a.bottomLeft,Ot,Et,!0),t.lineTo(i+n-a.bottomRight,s+o),t.arc(i+n-a.bottomRight,s+o-a.bottomRight,a.bottomRight,Et,0,!0),t.lineTo(i+n,s+a.topRight),t.arc(i+n-a.topRight,s+a.topRight,a.topRight,0,-Et,!0),t.lineTo(i+a.topLeft,s)}function Oe(t,e=[""],i=t,s,n=(()=>t[0])){ut(s)||(s=Ne("_fallback",t));const o={[Symbol.toStringTag]:"Object",_cacheable:!0,_scopes:t,_rootScopes:i,_fallback:s,_getTarget:n,override:n=>Oe([n,...t],e,i,s)};return new Proxy(o,{deleteProperty:(e,i)=>(delete e[i],delete e._keys,delete t[0][i],!0),get:(i,s)=>Ee(i,s,(()=>function(t,e,i,s){let n;for(const o of e)if(n=Ne(Le(o,t),i),ut(n))return Re(t,n)?Be(i,s,t,n):n}(s,e,t,i))),getOwnPropertyDescriptor:(t,e)=>Reflect.getOwnPropertyDescriptor(t._scopes[0],e),getPrototypeOf:()=>Reflect.getPrototypeOf(t[0]),has:(t,e)=>We(t).includes(e),ownKeys:t=>We(t),set(t,e,i){const s=t._storage||(t._storage=n());return t[e]=s[e]=i,delete t._keys,!0}})}function Ae(t,e,i,s){const n={_cacheable:!1,_proxy:t,_context:e,_subProxy:i,_stack:new Set,_descriptors:Te(t,s),setContext:e=>Ae(t,e,i,s),override:n=>Ae(t.override(n),e,i,s)};return new Proxy(n,{deleteProperty:(e,i)=>(delete e[i],delete t[i],!0),get:(t,e,i)=>Ee(t,e,(()=>function(t,e,i){const{_proxy:s,_context:n,_subProxy:o,_descriptors:a}=t;let r=s[e];ft(r)&&a.isScriptable(e)&&(r=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_stack:r}=i;if(r.has(t))throw new Error("Recursion detected: "+Array.from(r).join("->")+"->"+t);r.add(t),e=e(o,a||s),r.delete(t),Re(t,e)&&(e=Be(n._scopes,n,t,e));return e}(e,r,t,i));X(r)&&r.length&&(r=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_descriptors:r}=i;if(ut(o.index)&&s(t))e=e[o.index%e.length];else if(q(e[0])){const i=e,s=n._scopes.filter((t=>t!==i));e=[];for(const l of i){const i=Be(s,n,t,l);e.push(Ae(i,o,a&&a[t],r))}}return e}(e,r,t,a.isIndexable));Re(e,r)&&(r=Ae(r,n,o&&o[e],a));return r}(t,e,i))),getOwnPropertyDescriptor:(e,i)=>e._descriptors.allKeys?Reflect.has(t,i)?{enumerable:!0,configurable:!0}:void 0:Reflect.getOwnPropertyDescriptor(t,i),getPrototypeOf:()=>Reflect.getPrototypeOf(t),has:(e,i)=>Reflect.has(t,i),ownKeys:()=>Reflect.ownKeys(t),set:(e,i,s)=>(t[i]=s,delete e[i],!0)})}function Te(t,e={scriptable:!0,indexable:!0}){const{_scriptable:i=e.scriptable,_indexable:s=e.indexable,_allKeys:n=e.allKeys}=t;return{allKeys:n,scriptable:i,indexable:s,isScriptable:ft(i)?i:()=>i,isIndexable:ft(s)?s:()=>s}}const Le=(t,e)=>t?t+dt(e):e,Re=(t,e)=>q(e)&&"adapters"!==t&&(null===Object.getPrototypeOf(e)||e.constructor===Object);function Ee(t,e,i){if(Object.prototype.hasOwnProperty.call(t,e))return t[e];const s=i();return t[e]=s,s}function Ie(t,e,i){return ft(t)?t(e,i):t}const ze=(t,e)=>!0===t?e:"string"==typeof t?ct(e,t):void 0;function Fe(t,e,i,s,n){for(const o of e){const e=ze(i,o);if(e){t.add(e);const o=Ie(e._fallback,i,n);if(ut(o)&&o!==i&&o!==s)return o}else if(!1===e&&ut(s)&&i!==s)return null}return!1}function Be(t,e,i,s){const n=e._rootScopes,o=Ie(e._fallback,i,s),a=[...t,...n],r=new Set;r.add(s);let l=Ve(r,a,i,o||i,s);return null!==l&&((!ut(o)||o===i||(l=Ve(r,a,o,l,s),null!==l))&&Oe(Array.from(r),[""],n,o,(()=>function(t,e,i){const s=t._getTarget();e in s||(s[e]={});const n=s[e];if(X(n)&&q(i))return i;return n}(e,i,s))))}function Ve(t,e,i,s,n){for(;i;)i=Fe(t,e,i,s,n);return i}function Ne(t,e){for(const i of e){if(!i)continue;const e=i[t];if(ut(e))return e}}function We(t){let e=t._keys;return e||(e=t._keys=function(t){const e=new Set;for(const i of t)for(const t of Object.keys(i).filter((t=>!t.startsWith("_"))))e.add(t);return Array.from(e)}(t._scopes)),e}function He(t,e,i,s){const{iScale:n}=t,{key:o="r"}=this._parsing,a=new Array(s);let r,l,h,c;for(r=0,l=s;r<l;++r)h=r+i,c=e[h],a[r]={r:n.parse(ct(c,o),h)};return a}const je=Number.EPSILON||1e-14,$e=(t,e)=>e<t.length&&!t[e].skip&&t[e],Ye=t=>"x"===t?"y":"x";function Ue(t,e,i,s){const n=t.skip?e:t,o=e,a=i.skip?e:i,r=Kt(o,n),l=Kt(a,o);let h=r/(r+l),c=l/(r+l);h=isNaN(h)?0:h,c=isNaN(c)?0:c;const d=s*h,u=s*c;return{previous:{x:o.x-d*(a.x-n.x),y:o.y-d*(a.y-n.y)},next:{x:o.x+u*(a.x-n.x),y:o.y+u*(a.y-n.y)}}}function Xe(t,e="x"){const i=Ye(e),s=t.length,n=Array(s).fill(0),o=Array(s);let a,r,l,h=$e(t,0);for(a=0;a<s;++a)if(r=l,l=h,h=$e(t,a+1),l){if(h){const t=h[e]-l[e];n[a]=0!==t?(h[i]-l[i])/t:0}o[a]=r?h?Bt(n[a-1])!==Bt(n[a])?0:(n[a-1]+n[a])/2:n[a-1]:n[a]}!function(t,e,i){const s=t.length;let n,o,a,r,l,h=$e(t,0);for(let c=0;c<s-1;++c)l=h,h=$e(t,c+1),l&&h&&(Ht(e[c],0,je)?i[c]=i[c+1]=0:(n=i[c]/e[c],o=i[c+1]/e[c],r=Math.pow(n,2)+Math.pow(o,2),r<=9||(a=3/Math.sqrt(r),i[c]=n*a*e[c],i[c+1]=o*a*e[c])))}(t,n,o),function(t,e,i="x"){const s=Ye(i),n=t.length;let o,a,r,l=$e(t,0);for(let h=0;h<n;++h){if(a=r,r=l,l=$e(t,h+1),!r)continue;const n=r[i],c=r[s];a&&(o=(n-a[i])/3,r[`cp1${i}`]=n-o,r[`cp1${s}`]=c-o*e[h]),l&&(o=(l[i]-n)/3,r[`cp2${i}`]=n+o,r[`cp2${s}`]=c+o*e[h])}}(t,o,e)}function qe(t,e,i){return Math.max(Math.min(t,i),e)}function Ke(t,e,i,s,n){let o,a,r,l;if(e.spanGaps&&(t=t.filter((t=>!t.skip))),"monotone"===e.cubicInterpolationMode)Xe(t,n);else{let i=s?t[t.length-1]:t[0];for(o=0,a=t.length;o<a;++o)r=t[o],l=Ue(i,r,t[Math.min(o+1,a-(s?0:1))%a],e.tension),r.cp1x=l.previous.x,r.cp1y=l.previous.y,r.cp2x=l.next.x,r.cp2y=l.next.y,i=r}e.capBezierPoints&&function(t,e){let i,s,n,o,a,r=ve(t[0],e);for(i=0,s=t.length;i<s;++i)a=o,o=r,r=i<s-1&&ve(t[i+1],e),o&&(n=t[i],a&&(n.cp1x=qe(n.cp1x,e.left,e.right),n.cp1y=qe(n.cp1y,e.top,e.bottom)),r&&(n.cp2x=qe(n.cp2x,e.left,e.right),n.cp2y=qe(n.cp2y,e.top,e.bottom)))}(t,i)}const Ge=t=>0===t||1===t,Ze=(t,e,i)=>-Math.pow(2,10*(t-=1))*Math.sin((t-e)*At/i),Je=(t,e,i)=>Math.pow(2,-10*t)*Math.sin((t-e)*At/i)+1,Qe={linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>-t*(t-2),easeInOutQuad:t=>(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1),easeInCubic:t=>t*t*t,easeOutCubic:t=>(t-=1)*t*t+1,easeInOutCubic:t=>(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2),easeInQuart:t=>t*t*t*t,easeOutQuart:t=>-((t-=1)*t*t*t-1),easeInOutQuart:t=>(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2),easeInQuint:t=>t*t*t*t*t,easeOutQuint:t=>(t-=1)*t*t*t*t+1,easeInOutQuint:t=>(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2),easeInSine:t=>1-Math.cos(t*Et),easeOutSine:t=>Math.sin(t*Et),easeInOutSine:t=>-.5*(Math.cos(Ot*t)-1),easeInExpo:t=>0===t?0:Math.pow(2,10*(t-1)),easeOutExpo:t=>1===t?1:1-Math.pow(2,-10*t),easeInOutExpo:t=>Ge(t)?t:t<.5?.5*Math.pow(2,10*(2*t-1)):.5*(2-Math.pow(2,-10*(2*t-1))),easeInCirc:t=>t>=1?t:-(Math.sqrt(1-t*t)-1),easeOutCirc:t=>Math.sqrt(1-(t-=1)*t),easeInOutCirc:t=>(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1),easeInElastic:t=>Ge(t)?t:Ze(t,.075,.3),easeOutElastic:t=>Ge(t)?t:Je(t,.075,.3),easeInOutElastic(t){const e=.1125;return Ge(t)?t:t<.5?.5*Ze(2*t,e,.45):.5+.5*Je(2*t-1,e,.45)},easeInBack(t){const e=1.70158;return t*t*((e+1)*t-e)},easeOutBack(t){const e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack(t){let e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:t=>1-Qe.easeOutBounce(1-t),easeOutBounce(t){const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375},easeInOutBounce:t=>t<.5?.5*Qe.easeInBounce(2*t):.5*Qe.easeOutBounce(2*t-1)+.5};function ti(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:t.y+i*(e.y-t.y)}}function ei(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:"middle"===s?i<.5?t.y:e.y:"after"===s?i<1?t.y:e.y:i>0?e.y:t.y}}function ii(t,e,i,s){const n={x:t.cp2x,y:t.cp2y},o={x:e.cp1x,y:e.cp1y},a=ti(t,n,i),r=ti(n,o,i),l=ti(o,e,i),h=ti(a,r,i),c=ti(r,l,i);return ti(h,c,i)}const si=new Map;function ni(t,e,i){return function(t,e){e=e||{};const i=t+JSON.stringify(e);let s=si.get(i);return s||(s=new Intl.NumberFormat(t,e),si.set(i,s)),s}(e,i).format(t)}const oi=new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/),ai=new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);function ri(t,e){const i=(""+t).match(oi);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t}function li(t,e){const i={},s=q(e),n=s?Object.keys(e):e,o=q(t)?s?i=>Z(t[i],t[e[i]]):e=>t[e]:()=>t;for(const t of n)i[t]=+o(t)||0;return i}function hi(t){return li(t,{top:"y",right:"x",bottom:"y",left:"x"})}function ci(t){return li(t,["topLeft","topRight","bottomLeft","bottomRight"])}function di(t){const e=hi(t);return e.width=e.left+e.right,e.height=e.top+e.bottom,e}function ui(t,e){t=t||{},e=e||yt.font;let i=Z(t.size,e.size);"string"==typeof i&&(i=parseInt(i,10));let s=Z(t.style,e.style);s&&!(""+s).match(ai)&&(console.warn('Invalid font style specified: "'+s+'"'),s="");const n={family:Z(t.family,e.family),lineHeight:ri(Z(t.lineHeight,e.lineHeight),i),size:i,style:s,weight:Z(t.weight,e.weight),string:""};return n.string=pe(n),n}function fi(t,e,i,s){let n,o,a,r=!0;for(n=0,o=t.length;n<o;++n)if(a=t[n],void 0!==a&&(void 0!==e&&"function"==typeof a&&(a=a(e),r=!1),void 0!==i&&X(a)&&(a=a[i%a.length],r=!1),void 0!==a))return s&&!r&&(s.cacheable=!1),a}function gi(t,e,i){const{min:s,max:n}=t,o=Q(e,(n-s)/2),a=(t,e)=>i&&0===t?0:t+e;return{min:a(s,-Math.abs(o)),max:a(n,o)}}function pi(t,e){return Object.assign(Object.create(t),e)}function mi(t,e,i){return t?function(t,e){return{x:i=>t+t+e-i,setWidth(t){e=t},textAlign:t=>"center"===t?t:"right"===t?"left":"right",xPlus:(t,e)=>t-e,leftForLtr:(t,e)=>t-e}}(e,i):{x:t=>t,setWidth(t){},textAlign:t=>t,xPlus:(t,e)=>t+e,leftForLtr:(t,e)=>t}}function bi(t,e){let i,s;"ltr"!==e&&"rtl"!==e||(i=t.canvas.style,s=[i.getPropertyValue("direction"),i.getPropertyPriority("direction")],i.setProperty("direction",e,"important"),t.prevTextDirection=s)}function xi(t,e){void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}function _i(t){return"angle"===t?{between:Jt,compare:Gt,normalize:Zt}:{between:ee,compare:(t,e)=>t-e,normalize:t=>t}}function yi({start:t,end:e,count:i,loop:s,style:n}){return{start:t%i,end:e%i,loop:s&&(e-t+1)%i==0,style:n}}function vi(t,e,i){if(!i)return[t];const{property:s,start:n,end:o}=i,a=e.length,{compare:r,between:l,normalize:h}=_i(s),{start:c,end:d,loop:u,style:f}=function(t,e,i){const{property:s,start:n,end:o}=i,{between:a,normalize:r}=_i(s),l=e.length;let h,c,{start:d,end:u,loop:f}=t;if(f){for(d+=l,u+=l,h=0,c=l;h<c&&a(r(e[d%l][s]),n,o);++h)d--,u--;d%=l,u%=l}return u<d&&(u+=l),{start:d,end:u,loop:f,style:t.style}}(t,e,i),g=[];let p,m,b,x=!1,_=null;const y=()=>x||l(n,b,p)&&0!==r(n,b),v=()=>!x||0===r(o,p)||l(o,b,p);for(let t=c,i=c;t<=d;++t)m=e[t%a],m.skip||(p=h(m[s]),p!==b&&(x=l(p,n,o),null===_&&y()&&(_=0===r(p,n)?t:i),null!==_&&v()&&(g.push(yi({start:_,end:t,loop:u,count:a,style:f})),_=null),i=t,b=p));return null!==_&&g.push(yi({start:_,end:d,loop:u,count:a,style:f})),g}function wi(t,e){const i=[],s=t.segments;for(let n=0;n<s.length;n++){const o=vi(s[n],t.points,e);o.length&&i.push(...o)}return i}function Mi(t,e){const i=t.points,s=t.options.spanGaps,n=i.length;if(!n)return[];const o=!!t._loop,{start:a,end:r}=function(t,e,i,s){let n=0,o=e-1;if(i&&!s)for(;n<e&&!t[n].skip;)n++;for(;n<e&&t[n].skip;)n++;for(n%=e,i&&(o+=n);o>n&&t[o%e].skip;)o--;return o%=e,{start:n,end:o}}(i,n,o,s);if(!0===s)return ki(t,[{start:a,end:r,loop:o}],i,e);return ki(t,function(t,e,i,s){const n=t.length,o=[];let a,r=e,l=t[e];for(a=e+1;a<=i;++a){const i=t[a%n];i.skip||i.stop?l.skip||(s=!1,o.push({start:e%n,end:(a-1)%n,loop:s}),e=r=i.stop?a:null):(r=a,l.skip&&(e=a)),l=i}return null!==r&&o.push({start:e%n,end:r%n,loop:s}),o}(i,a,r<a?r+n:r,!!t._fullLoop&&0===a&&r===n-1),i,e)}function ki(t,e,i,s){return s&&s.setContext&&i?function(t,e,i,s){const n=t._chart.getContext(),o=Si(t.options),{_datasetIndex:a,options:{spanGaps:r}}=t,l=i.length,h=[];let c=o,d=e[0].start,u=d;function f(t,e,s,n){const o=r?-1:1;if(t!==e){for(t+=l;i[t%l].skip;)t-=o;for(;i[e%l].skip;)e+=o;t%l!=e%l&&(h.push({start:t%l,end:e%l,loop:s,style:n}),c=n,d=e%l)}}for(const t of e){d=r?d:t.start;let e,o=i[d%l];for(u=d+1;u<=t.end;u++){const r=i[u%l];e=Si(s.setContext(pi(n,{type:"segment",p0:o,p1:r,p0DataIndex:(u-1)%l,p1DataIndex:u%l,datasetIndex:a}))),Pi(e,c)&&f(d,u-1,t.loop,c),o=r,c=e}d<u-1&&f(d,u-1,t.loop,c)}return h}(t,e,i,s):e}function Si(t){return{backgroundColor:t.backgroundColor,borderCapStyle:t.borderCapStyle,borderDash:t.borderDash,borderDashOffset:t.borderDashOffset,borderJoinStyle:t.borderJoinStyle,borderWidth:t.borderWidth,borderColor:t.borderColor}}function Pi(t,e){return e&&JSON.stringify(t)!==JSON.stringify(e)}var Di=Object.freeze({__proto__:null,easingEffects:Qe,isPatternOrGradient:W,color:H,getHoverColor:j,noop:$,uid:Y,isNullOrUndef:U,isArray:X,isObject:q,isFinite:K,finiteOrDefault:G,valueOrDefault:Z,toPercentage:J,toDimension:Q,callback:tt,each:et,_elementsEqual:it,clone:st,_merger:ot,merge:at,mergeIf:rt,_mergerIf:lt,_deprecated:function(t,e,i,s){void 0!==e&&console.warn(t+': "'+i+'" is deprecated. Please use "'+s+'" instead')},resolveObjectKey:ct,_capitalize:dt,defined:ut,isFunction:ft,setsEqual:gt,_isClickEvent:pt,toFontString:pe,_measureText:me,_longestText:be,_alignPixel:xe,clearCanvas:_e,drawPoint:ye,_isPointInArea:ve,clipArea:we,unclipArea:Me,_steppedLineTo:ke,_bezierCurveTo:Se,renderText:Pe,addRoundedRectPath:Ce,_lookup:vt,_lookupByKey:wt,_rlookupByKey:Mt,_filterBetween:kt,listenArrayEvents:Pt,unlistenArrayEvents:Dt,_arrayUnique:Ct,_createResolver:Oe,_attachContext:Ae,_descriptors:Te,_parseObjectDataRadialScale:He,splineCurve:Ue,splineCurveMonotone:Xe,_updateBezierControlPoints:Ke,_isDomSupported:ie,_getParentNode:se,getStyle:ae,getRelativePosition:he,getMaximumSize:de,retinaScale:ue,supportsEventListenerOptions:fe,readUsedSize:ge,fontString:function(t,e,i){return e+" "+t+"px "+i},requestAnimFrame:t,throttled:e,debounce:i,_toLeftRightCenter:s,_alignStartEnd:n,_textX:o,_pointInLine:ti,_steppedInterpolation:ei,_bezierInterpolation:ii,formatNumber:ni,toLineHeight:ri,_readValueToProps:li,toTRBL:hi,toTRBLCorners:ci,toPadding:di,toFont:ui,resolve:fi,_addGrace:gi,createContext:pi,PI:Ot,TAU:At,PITAU:Tt,INFINITY:Lt,RAD_PER_DEG:Rt,HALF_PI:Et,QUARTER_PI:It,TWO_THIRDS_PI:zt,log10:Ft,sign:Bt,niceNum:Vt,_factorize:Nt,isNumber:Wt,almostEquals:Ht,almostWhole:jt,_setMinAndMaxByKey:$t,toRadians:Yt,toDegrees:Ut,_decimalPlaces:Xt,getAngleFromPoint:qt,distanceBetweenPoints:Kt,_angleDiff:Gt,_normalizeAngle:Zt,_angleBetween:Jt,_limitValue:Qt,_int16Range:te,_isBetween:ee,getRtlAdapter:mi,overrideTextDirection:bi,restoreTextDirection:xi,_boundSegment:vi,_boundSegments:wi,_computeSegments:Mi});function Ci(t,e,i,s){const{controller:n,data:o,_sorted:a}=t,r=n._cachedMeta.iScale;if(r&&e===r.axis&&"r"!==e&&a&&o.length){const t=r._reversePixels?Mt:wt;if(!s)return t(o,e,i);if(n._sharedOptions){const s=o[0],n="function"==typeof s.getRange&&s.getRange(e);if(n){const s=t(o,e,i-n),a=t(o,e,i+n);return{lo:s.lo,hi:a.hi}}}}return{lo:0,hi:o.length-1}}function Oi(t,e,i,s,n){const o=t.getSortedVisibleDatasetMetas(),a=i[e];for(let t=0,i=o.length;t<i;++t){const{index:i,data:r}=o[t],{lo:l,hi:h}=Ci(o[t],e,a,n);for(let t=l;t<=h;++t){const e=r[t];e.skip||s(e,i,t)}}}function Ai(t,e,i,s,n){const o=[];if(!n&&!t.isPointInArea(e))return o;return Oi(t,i,e,(function(i,a,r){(n||ve(i,t.chartArea,0))&&i.inRange(e.x,e.y,s)&&o.push({element:i,datasetIndex:a,index:r})}),!0),o}function Ti(t,e,i,s,n,o){let a=[];const r=function(t){const e=-1!==t.indexOf("x"),i=-1!==t.indexOf("y");return function(t,s){const n=e?Math.abs(t.x-s.x):0,o=i?Math.abs(t.y-s.y):0;return Math.sqrt(Math.pow(n,2)+Math.pow(o,2))}}(i);let l=Number.POSITIVE_INFINITY;return Oi(t,i,e,(function(i,h,c){const d=i.inRange(e.x,e.y,n);if(s&&!d)return;const u=i.getCenterPoint(n);if(!(!!o||t.isPointInArea(u))&&!d)return;const f=r(e,u);f<l?(a=[{element:i,datasetIndex:h,index:c}],l=f):f===l&&a.push({element:i,datasetIndex:h,index:c})})),a}function Li(t,e,i,s,n,o){return o||t.isPointInArea(e)?"r"!==i||s?Ti(t,e,i,s,n,o):function(t,e,i,s){let n=[];return Oi(t,i,e,(function(t,i,o){const{startAngle:a,endAngle:r}=t.getProps(["startAngle","endAngle"],s),{angle:l}=qt(t,{x:e.x,y:e.y});Jt(l,a,r)&&n.push({element:t,datasetIndex:i,index:o})})),n}(t,e,i,n):[]}function Ri(t,e,i,s,n){const o=[],a="x"===i?"inXRange":"inYRange";let r=!1;return Oi(t,i,e,((t,s,l)=>{t[a](e[i],n)&&(o.push({element:t,datasetIndex:s,index:l}),r=r||t.inRange(e.x,e.y,n))})),s&&!r?[]:o}var Ei={evaluateInteractionItems:Oi,modes:{index(t,e,i,s){const n=he(e,t),o=i.axis||"x",a=i.includeInvisible||!1,r=i.intersect?Ai(t,n,o,s,a):Li(t,n,o,!1,s,a),l=[];return r.length?(t.getSortedVisibleDatasetMetas().forEach((t=>{const e=r[0].index,i=t.data[e];i&&!i.skip&&l.push({element:i,datasetIndex:t.index,index:e})})),l):[]},dataset(t,e,i,s){const n=he(e,t),o=i.axis||"xy",a=i.includeInvisible||!1;let r=i.intersect?Ai(t,n,o,s,a):Li(t,n,o,!1,s,a);if(r.length>0){const e=r[0].datasetIndex,i=t.getDatasetMeta(e).data;r=[];for(let t=0;t<i.length;++t)r.push({element:i[t],datasetIndex:e,index:t})}return r},point:(t,e,i,s)=>Ai(t,he(e,t),i.axis||"xy",s,i.includeInvisible||!1),nearest(t,e,i,s){const n=he(e,t),o=i.axis||"xy",a=i.includeInvisible||!1;return Li(t,n,o,i.intersect,s,a)},x:(t,e,i,s)=>Ri(t,he(e,t),"x",i.intersect,s),y:(t,e,i,s)=>Ri(t,he(e,t),"y",i.intersect,s)}};const Ii=["left","top","right","bottom"];function zi(t,e){return t.filter((t=>t.pos===e))}function Fi(t,e){return t.filter((t=>-1===Ii.indexOf(t.pos)&&t.box.axis===e))}function Bi(t,e){return t.sort(((t,i)=>{const s=e?i:t,n=e?t:i;return s.weight===n.weight?s.index-n.index:s.weight-n.weight}))}function Vi(t,e){const i=function(t){const e={};for(const i of t){const{stack:t,pos:s,stackWeight:n}=i;if(!t||!Ii.includes(s))continue;const o=e[t]||(e[t]={count:0,placed:0,weight:0,size:0});o.count++,o.weight+=n}return e}(t),{vBoxMaxWidth:s,hBoxMaxHeight:n}=e;let o,a,r;for(o=0,a=t.length;o<a;++o){r=t[o];const{fullSize:a}=r.box,l=i[r.stack],h=l&&r.stackWeight/l.weight;r.horizontal?(r.width=h?h*s:a&&e.availableWidth,r.height=n):(r.width=s,r.height=h?h*n:a&&e.availableHeight)}return i}function Ni(t,e,i,s){return Math.max(t[i],e[i])+Math.max(t[s],e[s])}function Wi(t,e){t.top=Math.max(t.top,e.top),t.left=Math.max(t.left,e.left),t.bottom=Math.max(t.bottom,e.bottom),t.right=Math.max(t.right,e.right)}function Hi(t,e,i,s){const{pos:n,box:o}=i,a=t.maxPadding;if(!q(n)){i.size&&(t[n]-=i.size);const e=s[i.stack]||{size:0,count:1};e.size=Math.max(e.size,i.horizontal?o.height:o.width),i.size=e.size/e.count,t[n]+=i.size}o.getPadding&&Wi(a,o.getPadding());const r=Math.max(0,e.outerWidth-Ni(a,t,"left","right")),l=Math.max(0,e.outerHeight-Ni(a,t,"top","bottom")),h=r!==t.w,c=l!==t.h;return t.w=r,t.h=l,i.horizontal?{same:h,other:c}:{same:c,other:h}}function ji(t,e){const i=e.maxPadding;function s(t){const s={left:0,top:0,right:0,bottom:0};return t.forEach((t=>{s[t]=Math.max(e[t],i[t])})),s}return s(t?["left","right"]:["top","bottom"])}function $i(t,e,i,s){const n=[];let o,a,r,l,h,c;for(o=0,a=t.length,h=0;o<a;++o){r=t[o],l=r.box,l.update(r.width||e.w,r.height||e.h,ji(r.horizontal,e));const{same:a,other:d}=Hi(e,i,r,s);h|=a&&n.length,c=c||d,l.fullSize||n.push(r)}return h&&$i(n,e,i,s)||c}function Yi(t,e,i,s,n){t.top=i,t.left=e,t.right=e+s,t.bottom=i+n,t.width=s,t.height=n}function Ui(t,e,i,s){const n=i.padding;let{x:o,y:a}=e;for(const r of t){const t=r.box,l=s[r.stack]||{count:1,placed:0,weight:1},h=r.stackWeight/l.weight||1;if(r.horizontal){const s=e.w*h,o=l.size||t.height;ut(l.start)&&(a=l.start),t.fullSize?Yi(t,n.left,a,i.outerWidth-n.right-n.left,o):Yi(t,e.left+l.placed,a,s,o),l.start=a,l.placed+=s,a=t.bottom}else{const s=e.h*h,a=l.size||t.width;ut(l.start)&&(o=l.start),t.fullSize?Yi(t,o,n.top,a,i.outerHeight-n.bottom-n.top):Yi(t,o,e.top+l.placed,a,s),l.start=o,l.placed+=s,o=t.right}}e.x=o,e.y=a}yt.set("layout",{autoPadding:!0,padding:{top:0,right:0,bottom:0,left:0}});var Xi={addBox(t,e){t.boxes||(t.boxes=[]),e.fullSize=e.fullSize||!1,e.position=e.position||"top",e.weight=e.weight||0,e._layers=e._layers||function(){return[{z:0,draw(t){e.draw(t)}}]},t.boxes.push(e)},removeBox(t,e){const i=t.boxes?t.boxes.indexOf(e):-1;-1!==i&&t.boxes.splice(i,1)},configure(t,e,i){e.fullSize=i.fullSize,e.position=i.position,e.weight=i.weight},update(t,e,i,s){if(!t)return;const n=di(t.options.layout.padding),o=Math.max(e-n.width,0),a=Math.max(i-n.height,0),r=function(t){const e=function(t){const e=[];let i,s,n,o,a,r;for(i=0,s=(t||[]).length;i<s;++i)n=t[i],({position:o,options:{stack:a,stackWeight:r=1}}=n),e.push({index:i,box:n,pos:o,horizontal:n.isHorizontal(),weight:n.weight,stack:a&&o+a,stackWeight:r});return e}(t),i=Bi(e.filter((t=>t.box.fullSize)),!0),s=Bi(zi(e,"left"),!0),n=Bi(zi(e,"right")),o=Bi(zi(e,"top"),!0),a=Bi(zi(e,"bottom")),r=Fi(e,"x"),l=Fi(e,"y");return{fullSize:i,leftAndTop:s.concat(o),rightAndBottom:n.concat(l).concat(a).concat(r),chartArea:zi(e,"chartArea"),vertical:s.concat(n).concat(l),horizontal:o.concat(a).concat(r)}}(t.boxes),l=r.vertical,h=r.horizontal;et(t.boxes,(t=>{"function"==typeof t.beforeLayout&&t.beforeLayout()}));const c=l.reduce(((t,e)=>e.box.options&&!1===e.box.options.display?t:t+1),0)||1,d=Object.freeze({outerWidth:e,outerHeight:i,padding:n,availableWidth:o,availableHeight:a,vBoxMaxWidth:o/2/c,hBoxMaxHeight:a/2}),u=Object.assign({},n);Wi(u,di(s));const f=Object.assign({maxPadding:u,w:o,h:a,x:n.left,y:n.top},n),g=Vi(l.concat(h),d);$i(r.fullSize,f,d,g),$i(l,f,d,g),$i(h,f,d,g)&&$i(l,f,d,g),function(t){const e=t.maxPadding;function i(i){const s=Math.max(e[i]-t[i],0);return t[i]+=s,s}t.y+=i("top"),t.x+=i("left"),i("right"),i("bottom")}(f),Ui(r.leftAndTop,f,d,g),f.x+=f.w,f.y+=f.h,Ui(r.rightAndBottom,f,d,g),t.chartArea={left:f.left,top:f.top,right:f.left+f.w,bottom:f.top+f.h,height:f.h,width:f.w},et(r.chartArea,(e=>{const i=e.box;Object.assign(i,t.chartArea),i.update(f.w,f.h,{left:0,top:0,right:0,bottom:0})}))}};class qi{acquireContext(t,e){}releaseContext(t){return!1}addEventListener(t,e,i){}removeEventListener(t,e,i){}getDevicePixelRatio(){return 1}getMaximumSize(t,e,i,s){return e=Math.max(0,e||t.width),i=i||t.height,{width:e,height:Math.max(0,s?Math.floor(e/s):i)}}isAttached(t){return!0}updateConfig(t){}}class Ki extends qi{acquireContext(t){return t&&t.getContext&&t.getContext("2d")||null}updateConfig(t){t.options.animation=!1}}const Gi={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},Zi=t=>null===t||""===t;const Ji=!!fe&&{passive:!0};function Qi(t,e,i){t.canvas.removeEventListener(e,i,Ji)}function ts(t,e){for(const i of t)if(i===e||i.contains(e))return!0}function es(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||ts(i.addedNodes,s),e=e&&!ts(i.removedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}function is(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||ts(i.removedNodes,s),e=e&&!ts(i.addedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}const ss=new Map;let ns=0;function os(){const t=window.devicePixelRatio;t!==ns&&(ns=t,ss.forEach(((e,i)=>{i.currentDevicePixelRatio!==t&&e()})))}function as(t,i,s){const n=t.canvas,o=n&&se(n);if(!o)return;const a=e(((t,e)=>{const i=o.clientWidth;s(t,e),i<o.clientWidth&&s()}),window),r=new ResizeObserver((t=>{const e=t[0],i=e.contentRect.width,s=e.contentRect.height;0===i&&0===s||a(i,s)}));return r.observe(o),function(t,e){ss.size||window.addEventListener("resize",os),ss.set(t,e)}(t,a),r}function rs(t,e,i){i&&i.disconnect(),"resize"===e&&function(t){ss.delete(t),ss.size||window.removeEventListener("resize",os)}(t)}function ls(t,i,s){const n=t.canvas,o=e((e=>{null!==t.ctx&&s(function(t,e){const i=Gi[t.type]||t.type,{x:s,y:n}=he(t,e);return{type:i,chart:e,native:t,x:void 0!==s?s:null,y:void 0!==n?n:null}}(e,t))}),t,(t=>{const e=t[0];return[e,e.offsetX,e.offsetY]}));return function(t,e,i){t.addEventListener(e,i,Ji)}(n,i,o),o}class hs extends qi{acquireContext(t,e){const i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){const i=t.style,s=t.getAttribute("height"),n=t.getAttribute("width");if(t.$chartjs={initial:{height:s,width:n,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",i.boxSizing=i.boxSizing||"border-box",Zi(n)){const e=ge(t,"width");void 0!==e&&(t.width=e)}if(Zi(s))if(""===t.style.height)t.height=t.width/(e||2);else{const e=ge(t,"height");void 0!==e&&(t.height=e)}}(t,e),i):null}releaseContext(t){const e=t.canvas;if(!e.$chartjs)return!1;const i=e.$chartjs.initial;["height","width"].forEach((t=>{const s=i[t];U(s)?e.removeAttribute(t):e.setAttribute(t,s)}));const s=i.style||{};return Object.keys(s).forEach((t=>{e.style[t]=s[t]})),e.width=e.width,delete e.$chartjs,!0}addEventListener(t,e,i){this.removeEventListener(t,e);const s=t.$proxies||(t.$proxies={}),n={attach:es,detach:is,resize:as}[e]||ls;s[e]=n(t,e,i)}removeEventListener(t,e){const i=t.$proxies||(t.$proxies={}),s=i[e];if(!s)return;({attach:rs,detach:rs,resize:rs}[e]||Qi)(t,e,s),i[e]=void 0}getDevicePixelRatio(){return window.devicePixelRatio}getMaximumSize(t,e,i,s){return de(t,e,i,s)}isAttached(t){const e=se(t);return!(!e||!e.isConnected)}}function cs(t){return!ie()||"undefined"!=typeof OffscreenCanvas&&t instanceof OffscreenCanvas?Ki:hs}var ds=Object.freeze({__proto__:null,_detectPlatform:cs,BasePlatform:qi,BasicPlatform:Ki,DomPlatform:hs});const us="transparent",fs={boolean:(t,e,i)=>i>.5?e:t,color(t,e,i){const s=H(t||us),n=s.valid&&H(e||us);return n&&n.valid?n.mix(s,i).hexString():e},number:(t,e,i)=>t+(e-t)*i};class gs{constructor(t,e,i,s){const n=e[i];s=fi([t.to,s,n,t.from]);const o=fi([t.from,n,s]);this._active=!0,this._fn=t.fn||fs[t.type||typeof o],this._easing=Qe[t.easing]||Qe.linear,this._start=Math.floor(Date.now()+(t.delay||0)),this._duration=this._total=Math.floor(t.duration),this._loop=!!t.loop,this._target=e,this._prop=i,this._from=o,this._to=s,this._promises=void 0}active(){return this._active}update(t,e,i){if(this._active){this._notify(!1);const s=this._target[this._prop],n=i-this._start,o=this._duration-n;this._start=i,this._duration=Math.floor(Math.max(o,t.duration)),this._total+=n,this._loop=!!t.loop,this._to=fi([t.to,e,s,t.from]),this._from=fi([t.from,s,e])}}cancel(){this._active&&(this.tick(Date.now()),this._active=!1,this._notify(!1))}tick(t){const e=t-this._start,i=this._duration,s=this._prop,n=this._from,o=this._loop,a=this._to;let r;if(this._active=n!==a&&(o||e<i),!this._active)return this._target[s]=a,void this._notify(!0);e<0?this._target[s]=n:(r=e/i%2,r=o&&r>1?2-r:r,r=this._easing(Math.min(1,Math.max(0,r))),this._target[s]=this._fn(n,a,r))}wait(){const t=this._promises||(this._promises=[]);return new Promise(((e,i)=>{t.push({res:e,rej:i})}))}_notify(t){const e=t?"res":"rej",i=this._promises||[];for(let t=0;t<i.length;t++)i[t][e]()}}yt.set("animation",{delay:void 0,duration:1e3,easing:"easeOutQuart",fn:void 0,from:void 0,loop:void 0,to:void 0,type:void 0});const ps=Object.keys(yt.animation);yt.describe("animation",{_fallback:!1,_indexable:!1,_scriptable:t=>"onProgress"!==t&&"onComplete"!==t&&"fn"!==t}),yt.set("animations",{colors:{type:"color",properties:["color","borderColor","backgroundColor"]},numbers:{type:"number",properties:["x","y","borderWidth","radius","tension"]}}),yt.describe("animations",{_fallback:"animation"}),yt.set("transitions",{active:{animation:{duration:400}},resize:{animation:{duration:0}},show:{animations:{colors:{from:"transparent"},visible:{type:"boolean",duration:0}}},hide:{animations:{colors:{to:"transparent"},visible:{type:"boolean",easing:"linear",fn:t=>0|t}}}});class ms{constructor(t,e){this._chart=t,this._properties=new Map,this.configure(e)}configure(t){if(!q(t))return;const e=this._properties;Object.getOwnPropertyNames(t).forEach((i=>{const s=t[i];if(!q(s))return;const n={};for(const t of ps)n[t]=s[t];(X(s.properties)&&s.properties||[i]).forEach((t=>{t!==i&&e.has(t)||e.set(t,n)}))}))}_animateOptions(t,e){const i=e.options,s=function(t,e){if(!e)return;let i=t.options;if(!i)return void(t.options=e);i.$shared&&(t.options=i=Object.assign({},i,{$shared:!1,$animations:{}}));return i}(t,i);if(!s)return[];const n=this._createAnimations(s,i);return i.$shared&&function(t,e){const i=[],s=Object.keys(e);for(let e=0;e<s.length;e++){const n=t[s[e]];n&&n.active()&&i.push(n.wait())}return Promise.all(i)}(t.options.$animations,i).then((()=>{t.options=i}),(()=>{})),n}_createAnimations(t,e){const i=this._properties,s=[],n=t.$animations||(t.$animations={}),o=Object.keys(e),a=Date.now();let r;for(r=o.length-1;r>=0;--r){const l=o[r];if("$"===l.charAt(0))continue;if("options"===l){s.push(...this._animateOptions(t,e));continue}const h=e[l];let c=n[l];const d=i.get(l);if(c){if(d&&c.active()){c.update(d,h,a);continue}c.cancel()}d&&d.duration?(n[l]=c=new gs(d,t,l,h),s.push(c)):t[l]=h}return s}update(t,e){if(0===this._properties.size)return void Object.assign(t,e);const i=this._createAnimations(t,e);return i.length?(a.add(this._chart,i),!0):void 0}}function bs(t,e){const i=t&&t.options||{},s=i.reverse,n=void 0===i.min?e:0,o=void 0===i.max?e:0;return{start:s?o:n,end:s?n:o}}function xs(t,e){const i=[],s=t._getSortedDatasetMetas(e);let n,o;for(n=0,o=s.length;n<o;++n)i.push(s[n].index);return i}function _s(t,e,i,s={}){const n=t.keys,o="single"===s.mode;let a,r,l,h;if(null!==e){for(a=0,r=n.length;a<r;++a){if(l=+n[a],l===i){if(s.all)continue;break}h=t.values[l],K(h)&&(o||0===e||Bt(e)===Bt(h))&&(e+=h)}return e}}function ys(t,e){const i=t&&t.options.stacked;return i||void 0===i&&void 0!==e.stack}function vs(t,e,i){const s=t[e]||(t[e]={});return s[i]||(s[i]={})}function ws(t,e,i,s){for(const n of e.getMatchingVisibleMetas(s).reverse()){const e=t[n.index];if(i&&e>0||!i&&e<0)return n.index}return null}function Ms(t,e){const{chart:i,_cachedMeta:s}=t,n=i._stacks||(i._stacks={}),{iScale:o,vScale:a,index:r}=s,l=o.axis,h=a.axis,c=function(t,e,i){return`${t.id}.${e.id}.${i.stack||i.type}`}(o,a,s),d=e.length;let u;for(let t=0;t<d;++t){const i=e[t],{[l]:o,[h]:d}=i;u=(i._stacks||(i._stacks={}))[h]=vs(n,c,o),u[r]=d,u._top=ws(u,a,!0,s.type),u._bottom=ws(u,a,!1,s.type)}}function ks(t,e){const i=t.scales;return Object.keys(i).filter((t=>i[t].axis===e)).shift()}function Ss(t,e){const i=t.controller.index,s=t.vScale&&t.vScale.axis;if(s){e=e||t._parsed;for(const t of e){const e=t._stacks;if(!e||void 0===e[s]||void 0===e[s][i])return;delete e[s][i]}}}const Ps=t=>"reset"===t||"none"===t,Ds=(t,e)=>e?t:Object.assign({},t);class Cs{constructor(t,e){this.chart=t,this._ctx=t.ctx,this.index=e,this._cachedDataOpts={},this._cachedMeta=this.getMeta(),this._type=this._cachedMeta.type,this.options=void 0,this._parsing=!1,this._data=void 0,this._objectData=void 0,this._sharedOptions=void 0,this._drawStart=void 0,this._drawCount=void 0,this.enableOptionSharing=!1,this.supportsDecimation=!1,this.$context=void 0,this._syncList=[],this.initialize()}initialize(){const t=this._cachedMeta;this.configure(),this.linkScales(),t._stacked=ys(t.vScale,t),this.addElements()}updateIndex(t){this.index!==t&&Ss(this._cachedMeta),this.index=t}linkScales(){const t=this.chart,e=this._cachedMeta,i=this.getDataset(),s=(t,e,i,s)=>"x"===t?e:"r"===t?s:i,n=e.xAxisID=Z(i.xAxisID,ks(t,"x")),o=e.yAxisID=Z(i.yAxisID,ks(t,"y")),a=e.rAxisID=Z(i.rAxisID,ks(t,"r")),r=e.indexAxis,l=e.iAxisID=s(r,n,o,a),h=e.vAxisID=s(r,o,n,a);e.xScale=this.getScaleForId(n),e.yScale=this.getScaleForId(o),e.rScale=this.getScaleForId(a),e.iScale=this.getScaleForId(l),e.vScale=this.getScaleForId(h)}getDataset(){return this.chart.data.datasets[this.index]}getMeta(){return this.chart.getDatasetMeta(this.index)}getScaleForId(t){return this.chart.scales[t]}_getOtherScale(t){const e=this._cachedMeta;return t===e.iScale?e.vScale:e.iScale}reset(){this._update("reset")}_destroy(){const t=this._cachedMeta;this._data&&Dt(this._data,this),t._stacked&&Ss(t)}_dataCheck(){const t=this.getDataset(),e=t.data||(t.data=[]),i=this._data;if(q(e))this._data=function(t){const e=Object.keys(t),i=new Array(e.length);let s,n,o;for(s=0,n=e.length;s<n;++s)o=e[s],i[s]={x:o,y:t[o]};return i}(e);else if(i!==e){if(i){Dt(i,this);const t=this._cachedMeta;Ss(t),t._parsed=[]}e&&Object.isExtensible(e)&&Pt(e,this),this._syncList=[],this._data=e}}addElements(){const t=this._cachedMeta;this._dataCheck(),this.datasetElementType&&(t.dataset=new this.datasetElementType)}buildOrUpdateElements(t){const e=this._cachedMeta,i=this.getDataset();let s=!1;this._dataCheck();const n=e._stacked;e._stacked=ys(e.vScale,e),e.stack!==i.stack&&(s=!0,Ss(e),e.stack=i.stack),this._resyncElements(t),(s||n!==e._stacked)&&Ms(this,e._parsed)}configure(){const t=this.chart.config,e=t.datasetScopeKeys(this._type),i=t.getOptionScopes(this.getDataset(),e,!0);this.options=t.createResolver(i,this.getContext()),this._parsing=this.options.parsing,this._cachedDataOpts={}}parse(t,e){const{_cachedMeta:i,_data:s}=this,{iScale:n,_stacked:o}=i,a=n.axis;let r,l,h,c=0===t&&e===s.length||i._sorted,d=t>0&&i._parsed[t-1];if(!1===this._parsing)i._parsed=s,i._sorted=!0,h=s;else{h=X(s[t])?this.parseArrayData(i,s,t,e):q(s[t])?this.parseObjectData(i,s,t,e):this.parsePrimitiveData(i,s,t,e);const n=()=>null===l[a]||d&&l[a]<d[a];for(r=0;r<e;++r)i._parsed[r+t]=l=h[r],c&&(n()&&(c=!1),d=l);i._sorted=c}o&&Ms(this,h)}parsePrimitiveData(t,e,i,s){const{iScale:n,vScale:o}=t,a=n.axis,r=o.axis,l=n.getLabels(),h=n===o,c=new Array(s);let d,u,f;for(d=0,u=s;d<u;++d)f=d+i,c[d]={[a]:h||n.parse(l[f],f),[r]:o.parse(e[f],f)};return c}parseArrayData(t,e,i,s){const{xScale:n,yScale:o}=t,a=new Array(s);let r,l,h,c;for(r=0,l=s;r<l;++r)h=r+i,c=e[h],a[r]={x:n.parse(c[0],h),y:o.parse(c[1],h)};return a}parseObjectData(t,e,i,s){const{xScale:n,yScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l=new Array(s);let h,c,d,u;for(h=0,c=s;h<c;++h)d=h+i,u=e[d],l[h]={x:n.parse(ct(u,a),d),y:o.parse(ct(u,r),d)};return l}getParsed(t){return this._cachedMeta._parsed[t]}getDataElement(t){return this._cachedMeta.data[t]}applyStack(t,e,i){const s=this.chart,n=this._cachedMeta,o=e[t.axis];return _s({keys:xs(s,!0),values:e._stacks[t.axis]},o,n.index,{mode:i})}updateRangeFromParsed(t,e,i,s){const n=i[e.axis];let o=null===n?NaN:n;const a=s&&i._stacks[e.axis];s&&a&&(s.values=a,o=_s(s,n,this._cachedMeta.index)),t.min=Math.min(t.min,o),t.max=Math.max(t.max,o)}getMinMax(t,e){const i=this._cachedMeta,s=i._parsed,n=i._sorted&&t===i.iScale,o=s.length,a=this._getOtherScale(t),r=((t,e,i)=>t&&!e.hidden&&e._stacked&&{keys:xs(i,!0),values:null})(e,i,this.chart),l={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY},{min:h,max:c}=function(t){const{min:e,max:i,minDefined:s,maxDefined:n}=t.getUserBounds();return{min:s?e:Number.NEGATIVE_INFINITY,max:n?i:Number.POSITIVE_INFINITY}}(a);let d,u;function f(){u=s[d];const e=u[a.axis];return!K(u[t.axis])||h>e||c<e}for(d=0;d<o&&(f()||(this.updateRangeFromParsed(l,t,u,r),!n));++d);if(n)for(d=o-1;d>=0;--d)if(!f()){this.updateRangeFromParsed(l,t,u,r);break}return l}getAllParsedValues(t){const e=this._cachedMeta._parsed,i=[];let s,n,o;for(s=0,n=e.length;s<n;++s)o=e[s][t.axis],K(o)&&i.push(o);return i}getMaxOverflow(){return!1}getLabelAndValue(t){const e=this._cachedMeta,i=e.iScale,s=e.vScale,n=this.getParsed(t);return{label:i?""+i.getLabelForValue(n[i.axis]):"",value:s?""+s.getLabelForValue(n[s.axis]):""}}_update(t){const e=this._cachedMeta;this.update(t||"default"),e._clip=function(t){let e,i,s,n;return q(t)?(e=t.top,i=t.right,s=t.bottom,n=t.left):e=i=s=n=t,{top:e,right:i,bottom:s,left:n,disabled:!1===t}}(Z(this.options.clip,function(t,e,i){if(!1===i)return!1;const s=bs(t,i),n=bs(e,i);return{top:n.end,right:s.end,bottom:n.start,left:s.start}}(e.xScale,e.yScale,this.getMaxOverflow())))}update(t){}draw(){const t=this._ctx,e=this.chart,i=this._cachedMeta,s=i.data||[],n=e.chartArea,o=[],a=this._drawStart||0,r=this._drawCount||s.length-a,l=this.options.drawActiveElementsOnTop;let h;for(i.dataset&&i.dataset.draw(t,n,a,r),h=a;h<a+r;++h){const e=s[h];e.hidden||(e.active&&l?o.push(e):e.draw(t,n))}for(h=0;h<o.length;++h)o[h].draw(t,n)}getStyle(t,e){const i=e?"active":"default";return void 0===t&&this._cachedMeta.dataset?this.resolveDatasetElementOptions(i):this.resolveDataElementOptions(t||0,i)}getContext(t,e,i){const s=this.getDataset();let n;if(t>=0&&t<this._cachedMeta.data.length){const e=this._cachedMeta.data[t];n=e.$context||(e.$context=function(t,e,i){return pi(t,{active:!1,dataIndex:e,parsed:void 0,raw:void 0,element:i,index:e,mode:"default",type:"data"})}(this.getContext(),t,e)),n.parsed=this.getParsed(t),n.raw=s.data[t],n.index=n.dataIndex=t}else n=this.$context||(this.$context=function(t,e){return pi(t,{active:!1,dataset:void 0,datasetIndex:e,index:e,mode:"default",type:"dataset"})}(this.chart.getContext(),this.index)),n.dataset=s,n.index=n.datasetIndex=this.index;return n.active=!!e,n.mode=i,n}resolveDatasetElementOptions(t){return this._resolveElementOptions(this.datasetElementType.id,t)}resolveDataElementOptions(t,e){return this._resolveElementOptions(this.dataElementType.id,e,t)}_resolveElementOptions(t,e="default",i){const s="active"===e,n=this._cachedDataOpts,o=t+"-"+e,a=n[o],r=this.enableOptionSharing&&ut(i);if(a)return Ds(a,r);const l=this.chart.config,h=l.datasetElementScopeKeys(this._type,t),c=s?[`${t}Hover`,"hover",t,""]:[t,""],d=l.getOptionScopes(this.getDataset(),h),u=Object.keys(yt.elements[t]),f=l.resolveNamedOptions(d,u,(()=>this.getContext(i,s)),c);return f.$shared&&(f.$shared=r,n[o]=Object.freeze(Ds(f,r))),f}_resolveAnimations(t,e,i){const s=this.chart,n=this._cachedDataOpts,o=`animation-${e}`,a=n[o];if(a)return a;let r;if(!1!==s.options.animation){const s=this.chart.config,n=s.datasetAnimationScopeKeys(this._type,e),o=s.getOptionScopes(this.getDataset(),n);r=s.createResolver(o,this.getContext(t,i,e))}const l=new ms(s,r&&r.animations);return r&&r._cacheable&&(n[o]=Object.freeze(l)),l}getSharedOptions(t){if(t.$shared)return this._sharedOptions||(this._sharedOptions=Object.assign({},t))}includeOptions(t,e){return!e||Ps(t)||this.chart._animationsDisabled}updateElement(t,e,i,s){Ps(s)?Object.assign(t,i):this._resolveAnimations(e,s).update(t,i)}updateSharedOptions(t,e,i){t&&!Ps(e)&&this._resolveAnimations(void 0,e).update(t,i)}_setStyle(t,e,i,s){t.active=s;const n=this.getStyle(e,s);this._resolveAnimations(e,i,s).update(t,{options:!s&&this.getSharedOptions(n)||n})}removeHoverStyle(t,e,i){this._setStyle(t,i,"active",!1)}setHoverStyle(t,e,i){this._setStyle(t,i,"active",!0)}_removeDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!1)}_setDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!0)}_resyncElements(t){const e=this._data,i=this._cachedMeta.data;for(const[t,e,i]of this._syncList)this[t](e,i);this._syncList=[];const s=i.length,n=e.length,o=Math.min(n,s);o&&this.parse(0,o),n>s?this._insertElements(s,n-s,t):n<s&&this._removeElements(n,s-n)}_insertElements(t,e,i=!0){const s=this._cachedMeta,n=s.data,o=t+e;let a;const r=t=>{for(t.length+=e,a=t.length-1;a>=o;a--)t[a]=t[a-e]};for(r(n),a=t;a<o;++a)n[a]=new this.dataElementType;this._parsing&&r(s._parsed),this.parse(t,e),i&&this.updateElements(n,t,e,"reset")}updateElements(t,e,i,s){}_removeElements(t,e){const i=this._cachedMeta;if(this._parsing){const s=i._parsed.splice(t,e);i._stacked&&Ss(i,s)}i.data.splice(t,e)}_sync(t){if(this._parsing)this._syncList.push(t);else{const[e,i,s]=t;this[e](i,s)}this.chart._dataChanges.push([this.index,...t])}_onDataPush(){const t=arguments.length;this._sync(["_insertElements",this.getDataset().data.length-t,t])}_onDataPop(){this._sync(["_removeElements",this._cachedMeta.data.length-1,1])}_onDataShift(){this._sync(["_removeElements",0,1])}_onDataSplice(t,e){e&&this._sync(["_removeElements",t,e]);const i=arguments.length-2;i&&this._sync(["_insertElements",t,i])}_onDataUnshift(){this._sync(["_insertElements",0,arguments.length])}}Cs.defaults={},Cs.prototype.datasetElementType=null,Cs.prototype.dataElementType=null;class Os{constructor(){this.x=void 0,this.y=void 0,this.active=!1,this.options=void 0,this.$animations=void 0}tooltipPosition(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}hasValue(){return Wt(this.x)&&Wt(this.y)}getProps(t,e){const i=this.$animations;if(!e||!i)return this;const s={};return t.forEach((t=>{s[t]=i[t]&&i[t].active()?i[t]._to:this[t]})),s}}Os.defaults={},Os.defaultRoutes=void 0;const As={values:t=>X(t)?t:""+t,numeric(t,e,i){if(0===t)return"0";const s=this.chart.options.locale;let n,o=t;if(i.length>1){const e=Math.max(Math.abs(i[0].value),Math.abs(i[i.length-1].value));(e<1e-4||e>1e15)&&(n="scientific"),o=function(t,e){let i=e.length>3?e[2].value-e[1].value:e[1].value-e[0].value;Math.abs(i)>=1&&t!==Math.floor(t)&&(i=t-Math.floor(t));return i}(t,i)}const a=Ft(Math.abs(o)),r=Math.max(Math.min(-1*Math.floor(a),20),0),l={notation:n,minimumFractionDigits:r,maximumFractionDigits:r};return Object.assign(l,this.options.ticks.format),ni(t,s,l)},logarithmic(t,e,i){if(0===t)return"0";const s=t/Math.pow(10,Math.floor(Ft(t)));return 1===s||2===s||5===s?As.numeric.call(this,t,e,i):""}};var Ts={formatters:As};function Ls(t,e){const i=t.options.ticks,s=i.maxTicksLimit||function(t){const e=t.options.offset,i=t._tickSize(),s=t._length/i+(e?0:1),n=t._maxLength/i;return Math.floor(Math.min(s,n))}(t),n=i.major.enabled?function(t){const e=[];let i,s;for(i=0,s=t.length;i<s;i++)t[i].major&&e.push(i);return e}(e):[],o=n.length,a=n[0],r=n[o-1],l=[];if(o>s)return function(t,e,i,s){let n,o=0,a=i[0];for(s=Math.ceil(s),n=0;n<t.length;n++)n===a&&(e.push(t[n]),o++,a=i[o*s])}(e,l,n,o/s),l;const h=function(t,e,i){const s=function(t){const e=t.length;let i,s;if(e<2)return!1;for(s=t[0],i=1;i<e;++i)if(t[i]-t[i-1]!==s)return!1;return s}(t),n=e.length/i;if(!s)return Math.max(n,1);const o=Nt(s);for(let t=0,e=o.length-1;t<e;t++){const e=o[t];if(e>n)return e}return Math.max(n,1)}(n,e,s);if(o>0){let t,i;const s=o>1?Math.round((r-a)/(o-1)):null;for(Rs(e,l,h,U(s)?0:a-s,a),t=0,i=o-1;t<i;t++)Rs(e,l,h,n[t],n[t+1]);return Rs(e,l,h,r,U(s)?e.length:r+s),l}return Rs(e,l,h),l}function Rs(t,e,i,s,n){const o=Z(s,0),a=Math.min(Z(n,t.length),t.length);let r,l,h,c=0;for(i=Math.ceil(i),n&&(r=n-s,i=r/Math.floor(r/i)),h=o;h<0;)c++,h=Math.round(o+c*i);for(l=Math.max(o,0);l<a;l++)l===h&&(e.push(t[l]),c++,h=Math.round(o+c*i))}yt.set("scale",{display:!0,offset:!1,reverse:!1,beginAtZero:!1,bounds:"ticks",grace:0,grid:{display:!0,lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickLength:8,tickWidth:(t,e)=>e.lineWidth,tickColor:(t,e)=>e.color,offset:!1,borderDash:[],borderDashOffset:0,borderWidth:1},title:{display:!1,text:"",padding:{top:4,bottom:4}},ticks:{minRotation:0,maxRotation:50,mirror:!1,textStrokeWidth:0,textStrokeColor:"",padding:3,display:!0,autoSkip:!0,autoSkipPadding:3,labelOffset:0,callback:Ts.formatters.values,minor:{},major:{},align:"center",crossAlign:"near",showLabelBackdrop:!1,backdropColor:"rgba(255, 255, 255, 0.75)",backdropPadding:2}}),yt.route("scale.ticks","color","","color"),yt.route("scale.grid","color","","borderColor"),yt.route("scale.grid","borderColor","","borderColor"),yt.route("scale.title","color","","color"),yt.describe("scale",{_fallback:!1,_scriptable:t=>!t.startsWith("before")&&!t.startsWith("after")&&"callback"!==t&&"parser"!==t,_indexable:t=>"borderDash"!==t&&"tickBorderDash"!==t}),yt.describe("scales",{_fallback:"scale"}),yt.describe("scale.ticks",{_scriptable:t=>"backdropPadding"!==t&&"callback"!==t,_indexable:t=>"backdropPadding"!==t});const Es=(t,e,i)=>"top"===e||"left"===e?t[e]+i:t[e]-i;function Is(t,e){const i=[],s=t.length/e,n=t.length;let o=0;for(;o<n;o+=s)i.push(t[Math.floor(o)]);return i}function zs(t,e,i){const s=t.ticks.length,n=Math.min(e,s-1),o=t._startPixel,a=t._endPixel,r=1e-6;let l,h=t.getPixelForTick(n);if(!(i&&(l=1===s?Math.max(h-o,a-h):0===e?(t.getPixelForTick(1)-h)/2:(h-t.getPixelForTick(n-1))/2,h+=n<e?l:-l,h<o-r||h>a+r)))return h}function Fs(t){return t.drawTicks?t.tickLength:0}function Bs(t,e){if(!t.display)return 0;const i=ui(t.font,e),s=di(t.padding);return(X(t.text)?t.text.length:1)*i.lineHeight+s.height}function Vs(t,e,i){let n=s(t);return(i&&"right"!==e||!i&&"right"===e)&&(n=(t=>"left"===t?"right":"right"===t?"left":t)(n)),n}class Ns extends Os{constructor(t){super(),this.id=t.id,this.type=t.type,this.options=void 0,this.ctx=t.ctx,this.chart=t.chart,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this._margins={left:0,right:0,top:0,bottom:0},this.maxWidth=void 0,this.maxHeight=void 0,this.paddingTop=void 0,this.paddingBottom=void 0,this.paddingLeft=void 0,this.paddingRight=void 0,this.axis=void 0,this.labelRotation=void 0,this.min=void 0,this.max=void 0,this._range=void 0,this.ticks=[],this._gridLineItems=null,this._labelItems=null,this._labelSizes=null,this._length=0,this._maxLength=0,this._longestTextCache={},this._startPixel=void 0,this._endPixel=void 0,this._reversePixels=!1,this._userMax=void 0,this._userMin=void 0,this._suggestedMax=void 0,this._suggestedMin=void 0,this._ticksLength=0,this._borderValue=0,this._cache={},this._dataLimitsCached=!1,this.$context=void 0}init(t){this.options=t.setContext(this.getContext()),this.axis=t.axis,this._userMin=this.parse(t.min),this._userMax=this.parse(t.max),this._suggestedMin=this.parse(t.suggestedMin),this._suggestedMax=this.parse(t.suggestedMax)}parse(t,e){return t}getUserBounds(){let{_userMin:t,_userMax:e,_suggestedMin:i,_suggestedMax:s}=this;return t=G(t,Number.POSITIVE_INFINITY),e=G(e,Number.NEGATIVE_INFINITY),i=G(i,Number.POSITIVE_INFINITY),s=G(s,Number.NEGATIVE_INFINITY),{min:G(t,i),max:G(e,s),minDefined:K(t),maxDefined:K(e)}}getMinMax(t){let e,{min:i,max:s,minDefined:n,maxDefined:o}=this.getUserBounds();if(n&&o)return{min:i,max:s};const a=this.getMatchingVisibleMetas();for(let r=0,l=a.length;r<l;++r)e=a[r].controller.getMinMax(this,t),n||(i=Math.min(i,e.min)),o||(s=Math.max(s,e.max));return i=o&&i>s?s:i,s=n&&i>s?i:s,{min:G(i,G(s,i)),max:G(s,G(i,s))}}getPadding(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}}getTicks(){return this.ticks}getLabels(){const t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]}beforeLayout(){this._cache={},this._dataLimitsCached=!1}beforeUpdate(){tt(this.options.beforeUpdate,[this])}update(t,e,i){const{beginAtZero:s,grace:n,ticks:o}=this.options,a=o.sampleSize;this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this._margins=i=Object.assign({left:0,right:0,top:0,bottom:0},i),this.ticks=null,this._labelSizes=null,this._gridLineItems=null,this._labelItems=null,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this._maxLength=this.isHorizontal()?this.width+i.left+i.right:this.height+i.top+i.bottom,this._dataLimitsCached||(this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this._range=gi(this,n,s),this._dataLimitsCached=!0),this.beforeBuildTicks(),this.ticks=this.buildTicks()||[],this.afterBuildTicks();const r=a<this.ticks.length;this._convertTicksToLabels(r?Is(this.ticks,a):this.ticks),this.configure(),this.beforeCalculateLabelRotation(),this.calculateLabelRotation(),this.afterCalculateLabelRotation(),o.display&&(o.autoSkip||"auto"===o.source)&&(this.ticks=Ls(this,this.ticks),this._labelSizes=null,this.afterAutoSkip()),r&&this._convertTicksToLabels(this.ticks),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate()}configure(){let t,e,i=this.options.reverse;this.isHorizontal()?(t=this.left,e=this.right):(t=this.top,e=this.bottom,i=!i),this._startPixel=t,this._endPixel=e,this._reversePixels=i,this._length=e-t,this._alignToPixels=this.options.alignToPixels}afterUpdate(){tt(this.options.afterUpdate,[this])}beforeSetDimensions(){tt(this.options.beforeSetDimensions,[this])}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0}afterSetDimensions(){tt(this.options.afterSetDimensions,[this])}_callHooks(t){this.chart.notifyPlugins(t,this.getContext()),tt(this.options[t],[this])}beforeDataLimits(){this._callHooks("beforeDataLimits")}determineDataLimits(){}afterDataLimits(){this._callHooks("afterDataLimits")}beforeBuildTicks(){this._callHooks("beforeBuildTicks")}buildTicks(){return[]}afterBuildTicks(){this._callHooks("afterBuildTicks")}beforeTickToLabelConversion(){tt(this.options.beforeTickToLabelConversion,[this])}generateTickLabels(t){const e=this.options.ticks;let i,s,n;for(i=0,s=t.length;i<s;i++)n=t[i],n.label=tt(e.callback,[n.value,i,t],this)}afterTickToLabelConversion(){tt(this.options.afterTickToLabelConversion,[this])}beforeCalculateLabelRotation(){tt(this.options.beforeCalculateLabelRotation,[this])}calculateLabelRotation(){const t=this.options,e=t.ticks,i=this.ticks.length,s=e.minRotation||0,n=e.maxRotation;let o,a,r,l=s;if(!this._isVisible()||!e.display||s>=n||i<=1||!this.isHorizontal())return void(this.labelRotation=s);const h=this._getLabelSizes(),c=h.widest.width,d=h.highest.height,u=Qt(this.chart.width-c,0,this.maxWidth);o=t.offset?this.maxWidth/i:u/(i-1),c+6>o&&(o=u/(i-(t.offset?.5:1)),a=this.maxHeight-Fs(t.grid)-e.padding-Bs(t.title,this.chart.options.font),r=Math.sqrt(c*c+d*d),l=Ut(Math.min(Math.asin(Qt((h.highest.height+6)/o,-1,1)),Math.asin(Qt(a/r,-1,1))-Math.asin(Qt(d/r,-1,1)))),l=Math.max(s,Math.min(n,l))),this.labelRotation=l}afterCalculateLabelRotation(){tt(this.options.afterCalculateLabelRotation,[this])}afterAutoSkip(){}beforeFit(){tt(this.options.beforeFit,[this])}fit(){const t={width:0,height:0},{chart:e,options:{ticks:i,title:s,grid:n}}=this,o=this._isVisible(),a=this.isHorizontal();if(o){const o=Bs(s,e.options.font);if(a?(t.width=this.maxWidth,t.height=Fs(n)+o):(t.height=this.maxHeight,t.width=Fs(n)+o),i.display&&this.ticks.length){const{first:e,last:s,widest:n,highest:o}=this._getLabelSizes(),r=2*i.padding,l=Yt(this.labelRotation),h=Math.cos(l),c=Math.sin(l);if(a){const e=i.mirror?0:c*n.width+h*o.height;t.height=Math.min(this.maxHeight,t.height+e+r)}else{const e=i.mirror?0:h*n.width+c*o.height;t.width=Math.min(this.maxWidth,t.width+e+r)}this._calculatePadding(e,s,c,h)}}this._handleMargins(),a?(this.width=this._length=e.width-this._margins.left-this._margins.right,this.height=t.height):(this.width=t.width,this.height=this._length=e.height-this._margins.top-this._margins.bottom)}_calculatePadding(t,e,i,s){const{ticks:{align:n,padding:o},position:a}=this.options,r=0!==this.labelRotation,l="top"!==a&&"x"===this.axis;if(this.isHorizontal()){const a=this.getPixelForTick(0)-this.left,h=this.right-this.getPixelForTick(this.ticks.length-1);let c=0,d=0;r?l?(c=s*t.width,d=i*e.height):(c=i*t.height,d=s*e.width):"start"===n?d=e.width:"end"===n?c=t.width:"inner"!==n&&(c=t.width/2,d=e.width/2),this.paddingLeft=Math.max((c-a+o)*this.width/(this.width-a),0),this.paddingRight=Math.max((d-h+o)*this.width/(this.width-h),0)}else{let i=e.height/2,s=t.height/2;"start"===n?(i=0,s=t.height):"end"===n&&(i=e.height,s=0),this.paddingTop=i+o,this.paddingBottom=s+o}}_handleMargins(){this._margins&&(this._margins.left=Math.max(this.paddingLeft,this._margins.left),this._margins.top=Math.max(this.paddingTop,this._margins.top),this._margins.right=Math.max(this.paddingRight,this._margins.right),this._margins.bottom=Math.max(this.paddingBottom,this._margins.bottom))}afterFit(){tt(this.options.afterFit,[this])}isHorizontal(){const{axis:t,position:e}=this.options;return"top"===e||"bottom"===e||"x"===t}isFullSize(){return this.options.fullSize}_convertTicksToLabels(t){let e,i;for(this.beforeTickToLabelConversion(),this.generateTickLabels(t),e=0,i=t.length;e<i;e++)U(t[e].label)&&(t.splice(e,1),i--,e--);this.afterTickToLabelConversion()}_getLabelSizes(){let t=this._labelSizes;if(!t){const e=this.options.ticks.sampleSize;let i=this.ticks;e<i.length&&(i=Is(i,e)),this._labelSizes=t=this._computeLabelSizes(i,i.length)}return t}_computeLabelSizes(t,e){const{ctx:i,_longestTextCache:s}=this,n=[],o=[];let a,r,l,h,c,d,u,f,g,p,m,b=0,x=0;for(a=0;a<e;++a){if(h=t[a].label,c=this._resolveTickFontOptions(a),i.font=d=c.string,u=s[d]=s[d]||{data:{},gc:[]},f=c.lineHeight,g=p=0,U(h)||X(h)){if(X(h))for(r=0,l=h.length;r<l;++r)m=h[r],U(m)||X(m)||(g=me(i,u.data,u.gc,g,m),p+=f)}else g=me(i,u.data,u.gc,g,h),p=f;n.push(g),o.push(p),b=Math.max(g,b),x=Math.max(p,x)}!function(t,e){et(t,(t=>{const i=t.gc,s=i.length/2;let n;if(s>e){for(n=0;n<s;++n)delete t.data[i[n]];i.splice(0,s)}}))}(s,e);const _=n.indexOf(b),y=o.indexOf(x),v=t=>({width:n[t]||0,height:o[t]||0});return{first:v(0),last:v(e-1),widest:v(_),highest:v(y),widths:n,heights:o}}getLabelForValue(t){return t}getPixelForValue(t,e){return NaN}getValueForPixel(t){}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getPixelForDecimal(t){this._reversePixels&&(t=1-t);const e=this._startPixel+t*this._length;return te(this._alignToPixels?xe(this.chart,e,0):e)}getDecimalForPixel(t){const e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:e}=this;return t<0&&e<0?e:t>0&&e>0?t:0}getContext(t){const e=this.ticks||[];if(t>=0&&t<e.length){const i=e[t];return i.$context||(i.$context=function(t,e,i){return pi(t,{tick:i,index:e,type:"tick"})}(this.getContext(),t,i))}return this.$context||(this.$context=pi(this.chart.getContext(),{scale:this,type:"scale"}))}_tickSize(){const t=this.options.ticks,e=Yt(this.labelRotation),i=Math.abs(Math.cos(e)),s=Math.abs(Math.sin(e)),n=this._getLabelSizes(),o=t.autoSkipPadding||0,a=n?n.widest.width+o:0,r=n?n.highest.height+o:0;return this.isHorizontal()?r*i>a*s?a/i:r/s:r*s<a*i?r/i:a/s}_isVisible(){const t=this.options.display;return"auto"!==t?!!t:this.getMatchingVisibleMetas().length>0}_computeGridLineItems(t){const e=this.axis,i=this.chart,s=this.options,{grid:n,position:o}=s,a=n.offset,r=this.isHorizontal(),l=this.ticks.length+(a?1:0),h=Fs(n),c=[],d=n.setContext(this.getContext()),u=d.drawBorder?d.borderWidth:0,f=u/2,g=function(t){return xe(i,t,u)};let p,m,b,x,_,y,v,w,M,k,S,P;if("top"===o)p=g(this.bottom),y=this.bottom-h,w=p-f,k=g(t.top)+f,P=t.bottom;else if("bottom"===o)p=g(this.top),k=t.top,P=g(t.bottom)-f,y=p+f,w=this.top+h;else if("left"===o)p=g(this.right),_=this.right-h,v=p-f,M=g(t.left)+f,S=t.right;else if("right"===o)p=g(this.left),M=t.left,S=g(t.right)-f,_=p+f,v=this.left+h;else if("x"===e){if("center"===o)p=g((t.top+t.bottom)/2+.5);else if(q(o)){const t=Object.keys(o)[0],e=o[t];p=g(this.chart.scales[t].getPixelForValue(e))}k=t.top,P=t.bottom,y=p+f,w=y+h}else if("y"===e){if("center"===o)p=g((t.left+t.right)/2);else if(q(o)){const t=Object.keys(o)[0],e=o[t];p=g(this.chart.scales[t].getPixelForValue(e))}_=p-f,v=_-h,M=t.left,S=t.right}const D=Z(s.ticks.maxTicksLimit,l),C=Math.max(1,Math.ceil(l/D));for(m=0;m<l;m+=C){const t=n.setContext(this.getContext(m)),e=t.lineWidth,s=t.color,o=n.borderDash||[],l=t.borderDashOffset,h=t.tickWidth,d=t.tickColor,u=t.tickBorderDash||[],f=t.tickBorderDashOffset;b=zs(this,m,a),void 0!==b&&(x=xe(i,b,e),r?_=v=M=S=x:y=w=k=P=x,c.push({tx1:_,ty1:y,tx2:v,ty2:w,x1:M,y1:k,x2:S,y2:P,width:e,color:s,borderDash:o,borderDashOffset:l,tickWidth:h,tickColor:d,tickBorderDash:u,tickBorderDashOffset:f}))}return this._ticksLength=l,this._borderValue=p,c}_computeLabelItems(t){const e=this.axis,i=this.options,{position:s,ticks:n}=i,o=this.isHorizontal(),a=this.ticks,{align:r,crossAlign:l,padding:h,mirror:c}=n,d=Fs(i.grid),u=d+h,f=c?-h:u,g=-Yt(this.labelRotation),p=[];let m,b,x,_,y,v,w,M,k,S,P,D,C="middle";if("top"===s)v=this.bottom-f,w=this._getXAxisLabelAlignment();else if("bottom"===s)v=this.top+f,w=this._getXAxisLabelAlignment();else if("left"===s){const t=this._getYAxisLabelAlignment(d);w=t.textAlign,y=t.x}else if("right"===s){const t=this._getYAxisLabelAlignment(d);w=t.textAlign,y=t.x}else if("x"===e){if("center"===s)v=(t.top+t.bottom)/2+u;else if(q(s)){const t=Object.keys(s)[0],e=s[t];v=this.chart.scales[t].getPixelForValue(e)+u}w=this._getXAxisLabelAlignment()}else if("y"===e){if("center"===s)y=(t.left+t.right)/2-u;else if(q(s)){const t=Object.keys(s)[0],e=s[t];y=this.chart.scales[t].getPixelForValue(e)}w=this._getYAxisLabelAlignment(d).textAlign}"y"===e&&("start"===r?C="top":"end"===r&&(C="bottom"));const O=this._getLabelSizes();for(m=0,b=a.length;m<b;++m){x=a[m],_=x.label;const t=n.setContext(this.getContext(m));M=this.getPixelForTick(m)+n.labelOffset,k=this._resolveTickFontOptions(m),S=k.lineHeight,P=X(_)?_.length:1;const e=P/2,i=t.color,r=t.textStrokeColor,h=t.textStrokeWidth;let d,u=w;if(o?(y=M,"inner"===w&&(u=m===b-1?this.options.reverse?"left":"right":0===m?this.options.reverse?"right":"left":"center"),D="top"===s?"near"===l||0!==g?-P*S+S/2:"center"===l?-O.highest.height/2-e*S+S:-O.highest.height+S/2:"near"===l||0!==g?S/2:"center"===l?O.highest.height/2-e*S:O.highest.height-P*S,c&&(D*=-1)):(v=M,D=(1-P)*S/2),t.showLabelBackdrop){const e=di(t.backdropPadding),i=O.heights[m],s=O.widths[m];let n=v+D-e.top,o=y-e.left;switch(C){case"middle":n-=i/2;break;case"bottom":n-=i}switch(w){case"center":o-=s/2;break;case"right":o-=s}d={left:o,top:n,width:s+e.width,height:i+e.height,color:t.backdropColor}}p.push({rotation:g,label:_,font:k,color:i,strokeColor:r,strokeWidth:h,textOffset:D,textAlign:u,textBaseline:C,translation:[y,v],backdrop:d})}return p}_getXAxisLabelAlignment(){const{position:t,ticks:e}=this.options;if(-Yt(this.labelRotation))return"top"===t?"left":"right";let i="center";return"start"===e.align?i="left":"end"===e.align?i="right":"inner"===e.align&&(i="inner"),i}_getYAxisLabelAlignment(t){const{position:e,ticks:{crossAlign:i,mirror:s,padding:n}}=this.options,o=t+n,a=this._getLabelSizes().widest.width;let r,l;return"left"===e?s?(l=this.right+n,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l+=a)):(l=this.right-o,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l=this.left)):"right"===e?s?(l=this.left+n,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l-=a)):(l=this.left+o,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l=this.right)):r="right",{textAlign:r,x:l}}_computeLabelArea(){if(this.options.ticks.mirror)return;const t=this.chart,e=this.options.position;return"left"===e||"right"===e?{top:0,left:this.left,bottom:t.height,right:this.right}:"top"===e||"bottom"===e?{top:this.top,left:0,bottom:this.bottom,right:t.width}:void 0}drawBackground(){const{ctx:t,options:{backgroundColor:e},left:i,top:s,width:n,height:o}=this;e&&(t.save(),t.fillStyle=e,t.fillRect(i,s,n,o),t.restore())}getLineWidthForValue(t){const e=this.options.grid;if(!this._isVisible()||!e.display)return 0;const i=this.ticks.findIndex((e=>e.value===t));if(i>=0){return e.setContext(this.getContext(i)).lineWidth}return 0}drawGrid(t){const e=this.options.grid,i=this.ctx,s=this._gridLineItems||(this._gridLineItems=this._computeGridLineItems(t));let n,o;const a=(t,e,s)=>{s.width&&s.color&&(i.save(),i.lineWidth=s.width,i.strokeStyle=s.color,i.setLineDash(s.borderDash||[]),i.lineDashOffset=s.borderDashOffset,i.beginPath(),i.moveTo(t.x,t.y),i.lineTo(e.x,e.y),i.stroke(),i.restore())};if(e.display)for(n=0,o=s.length;n<o;++n){const t=s[n];e.drawOnChartArea&&a({x:t.x1,y:t.y1},{x:t.x2,y:t.y2},t),e.drawTicks&&a({x:t.tx1,y:t.ty1},{x:t.tx2,y:t.ty2},{color:t.tickColor,width:t.tickWidth,borderDash:t.tickBorderDash,borderDashOffset:t.tickBorderDashOffset})}}drawBorder(){const{chart:t,ctx:e,options:{grid:i}}=this,s=i.setContext(this.getContext()),n=i.drawBorder?s.borderWidth:0;if(!n)return;const o=i.setContext(this.getContext(0)).lineWidth,a=this._borderValue;let r,l,h,c;this.isHorizontal()?(r=xe(t,this.left,n)-n/2,l=xe(t,this.right,o)+o/2,h=c=a):(h=xe(t,this.top,n)-n/2,c=xe(t,this.bottom,o)+o/2,r=l=a),e.save(),e.lineWidth=s.borderWidth,e.strokeStyle=s.borderColor,e.beginPath(),e.moveTo(r,h),e.lineTo(l,c),e.stroke(),e.restore()}drawLabels(t){if(!this.options.ticks.display)return;const e=this.ctx,i=this._computeLabelArea();i&&we(e,i);const s=this._labelItems||(this._labelItems=this._computeLabelItems(t));let n,o;for(n=0,o=s.length;n<o;++n){const t=s[n],i=t.font,o=t.label;t.backdrop&&(e.fillStyle=t.backdrop.color,e.fillRect(t.backdrop.left,t.backdrop.top,t.backdrop.width,t.backdrop.height)),Pe(e,o,0,t.textOffset,i,t)}i&&Me(e)}drawTitle(){const{ctx:t,options:{position:e,title:i,reverse:s}}=this;if(!i.display)return;const o=ui(i.font),a=di(i.padding),r=i.align;let l=o.lineHeight/2;"bottom"===e||"center"===e||q(e)?(l+=a.bottom,X(i.text)&&(l+=o.lineHeight*(i.text.length-1))):l+=a.top;const{titleX:h,titleY:c,maxWidth:d,rotation:u}=function(t,e,i,s){const{top:o,left:a,bottom:r,right:l,chart:h}=t,{chartArea:c,scales:d}=h;let u,f,g,p=0;const m=r-o,b=l-a;if(t.isHorizontal()){if(f=n(s,a,l),q(i)){const t=Object.keys(i)[0],s=i[t];g=d[t].getPixelForValue(s)+m-e}else g="center"===i?(c.bottom+c.top)/2+m-e:Es(t,i,e);u=l-a}else{if(q(i)){const t=Object.keys(i)[0],s=i[t];f=d[t].getPixelForValue(s)-b+e}else f="center"===i?(c.left+c.right)/2-b+e:Es(t,i,e);g=n(s,r,o),p="left"===i?-Et:Et}return{titleX:f,titleY:g,maxWidth:u,rotation:p}}(this,l,e,r);Pe(t,i.text,0,0,o,{color:i.color,maxWidth:d,rotation:u,textAlign:Vs(r,e,s),textBaseline:"middle",translation:[h,c]})}draw(t){this._isVisible()&&(this.drawBackground(),this.drawGrid(t),this.drawBorder(),this.drawTitle(),this.drawLabels(t))}_layers(){const t=this.options,e=t.ticks&&t.ticks.z||0,i=Z(t.grid&&t.grid.z,-1);return this._isVisible()&&this.draw===Ns.prototype.draw?[{z:i,draw:t=>{this.drawBackground(),this.drawGrid(t),this.drawTitle()}},{z:i+1,draw:()=>{this.drawBorder()}},{z:e,draw:t=>{this.drawLabels(t)}}]:[{z:e,draw:t=>{this.draw(t)}}]}getMatchingVisibleMetas(t){const e=this.chart.getSortedVisibleDatasetMetas(),i=this.axis+"AxisID",s=[];let n,o;for(n=0,o=e.length;n<o;++n){const o=e[n];o[i]!==this.id||t&&o.type!==t||s.push(o)}return s}_resolveTickFontOptions(t){return ui(this.options.ticks.setContext(this.getContext(t)).font)}_maxDigits(){const t=this._resolveTickFontOptions(0).lineHeight;return(this.isHorizontal()?this.width:this.height)/t}}class Ws{constructor(t,e,i){this.type=t,this.scope=e,this.override=i,this.items=Object.create(null)}isForType(t){return Object.prototype.isPrototypeOf.call(this.type.prototype,t.prototype)}register(t){const e=Object.getPrototypeOf(t);let i;(function(t){return"id"in t&&"defaults"in t})(e)&&(i=this.register(e));const s=this.items,n=t.id,o=this.scope+"."+n;if(!n)throw new Error("class does not have id: "+t);return n in s||(s[n]=t,function(t,e,i){const s=at(Object.create(null),[i?yt.get(i):{},yt.get(e),t.defaults]);yt.set(e,s),t.defaultRoutes&&function(t,e){Object.keys(e).forEach((i=>{const s=i.split("."),n=s.pop(),o=[t].concat(s).join("."),a=e[i].split("."),r=a.pop(),l=a.join(".");yt.route(o,n,l,r)}))}(e,t.defaultRoutes);t.descriptors&&yt.describe(e,t.descriptors)}(t,o,i),this.override&&yt.override(t.id,t.overrides)),o}get(t){return this.items[t]}unregister(t){const e=this.items,i=t.id,s=this.scope;i in e&&delete e[i],s&&i in yt[s]&&(delete yt[s][i],this.override&&delete mt[i])}}var Hs=new class{constructor(){this.controllers=new Ws(Cs,"datasets",!0),this.elements=new Ws(Os,"elements"),this.plugins=new Ws(Object,"plugins"),this.scales=new Ws(Ns,"scales"),this._typedRegistries=[this.controllers,this.scales,this.elements]}add(...t){this._each("register",t)}remove(...t){this._each("unregister",t)}addControllers(...t){this._each("register",t,this.controllers)}addElements(...t){this._each("register",t,this.elements)}addPlugins(...t){this._each("register",t,this.plugins)}addScales(...t){this._each("register",t,this.scales)}getController(t){return this._get(t,this.controllers,"controller")}getElement(t){return this._get(t,this.elements,"element")}getPlugin(t){return this._get(t,this.plugins,"plugin")}getScale(t){return this._get(t,this.scales,"scale")}removeControllers(...t){this._each("unregister",t,this.controllers)}removeElements(...t){this._each("unregister",t,this.elements)}removePlugins(...t){this._each("unregister",t,this.plugins)}removeScales(...t){this._each("unregister",t,this.scales)}_each(t,e,i){[...e].forEach((e=>{const s=i||this._getRegistryForType(e);i||s.isForType(e)||s===this.plugins&&e.id?this._exec(t,s,e):et(e,(e=>{const s=i||this._getRegistryForType(e);this._exec(t,s,e)}))}))}_exec(t,e,i){const s=dt(t);tt(i["before"+s],[],i),e[t](i),tt(i["after"+s],[],i)}_getRegistryForType(t){for(let e=0;e<this._typedRegistries.length;e++){const i=this._typedRegistries[e];if(i.isForType(t))return i}return this.plugins}_get(t,e,i){const s=e.get(t);if(void 0===s)throw new Error('"'+t+'" is not a registered '+i+".");return s}};class js{constructor(){this._init=[]}notify(t,e,i,s){"beforeInit"===e&&(this._init=this._createDescriptors(t,!0),this._notify(this._init,t,"install"));const n=s?this._descriptors(t).filter(s):this._descriptors(t),o=this._notify(n,t,e,i);return"afterDestroy"===e&&(this._notify(n,t,"stop"),this._notify(this._init,t,"uninstall")),o}_notify(t,e,i,s){s=s||{};for(const n of t){const t=n.plugin;if(!1===tt(t[i],[e,s,n.options],t)&&s.cancelable)return!1}return!0}invalidate(){U(this._cache)||(this._oldCache=this._cache,this._cache=void 0)}_descriptors(t){if(this._cache)return this._cache;const e=this._cache=this._createDescriptors(t);return this._notifyStateChanges(t),e}_createDescriptors(t,e){const i=t&&t.config,s=Z(i.options&&i.options.plugins,{}),n=function(t){const e=[],i=Object.keys(Hs.plugins.items);for(let t=0;t<i.length;t++)e.push(Hs.getPlugin(i[t]));const s=t.plugins||[];for(let t=0;t<s.length;t++){const i=s[t];-1===e.indexOf(i)&&e.push(i)}return e}(i);return!1!==s||e?function(t,e,i,s){const n=[],o=t.getContext();for(let a=0;a<e.length;a++){const r=e[a],l=$s(i[r.id],s);null!==l&&n.push({plugin:r,options:Ys(t.config,r,l,o)})}return n}(t,n,s,e):[]}_notifyStateChanges(t){const e=this._oldCache||[],i=this._cache,s=(t,e)=>t.filter((t=>!e.some((e=>t.plugin.id===e.plugin.id))));this._notify(s(e,i),t,"stop"),this._notify(s(i,e),t,"start")}}function $s(t,e){return e||!1!==t?!0===t?{}:t:null}function Ys(t,e,i,s){const n=t.pluginScopeKeys(e),o=t.getOptionScopes(i,n);return t.createResolver(o,s,[""],{scriptable:!1,indexable:!1,allKeys:!0})}function Us(t,e){const i=yt.datasets[t]||{};return((e.datasets||{})[t]||{}).indexAxis||e.indexAxis||i.indexAxis||"x"}function Xs(t,e){return"x"===t||"y"===t?t:e.axis||("top"===(i=e.position)||"bottom"===i?"x":"left"===i||"right"===i?"y":void 0)||t.charAt(0).toLowerCase();var i}function qs(t){const e=t.options||(t.options={});e.plugins=Z(e.plugins,{}),e.scales=function(t,e){const i=mt[t.type]||{scales:{}},s=e.scales||{},n=Us(t.type,e),o=Object.create(null),a=Object.create(null);return Object.keys(s).forEach((t=>{const e=s[t];if(!q(e))return console.error(`Invalid scale configuration for scale: ${t}`);if(e._proxy)return console.warn(`Ignoring resolver passed as options for scale: ${t}`);const r=Xs(t,e),l=function(t,e){return t===e?"_index_":"_value_"}(r,n),h=i.scales||{};o[r]=o[r]||t,a[t]=rt(Object.create(null),[{axis:r},e,h[r],h[l]])})),t.data.datasets.forEach((i=>{const n=i.type||t.type,r=i.indexAxis||Us(n,e),l=(mt[n]||{}).scales||{};Object.keys(l).forEach((t=>{const e=function(t,e){let i=t;return"_index_"===t?i=e:"_value_"===t&&(i="x"===e?"y":"x"),i}(t,r),n=i[e+"AxisID"]||o[e]||e;a[n]=a[n]||Object.create(null),rt(a[n],[{axis:e},s[n],l[t]])}))})),Object.keys(a).forEach((t=>{const e=a[t];rt(e,[yt.scales[e.type],yt.scale])})),a}(t,e)}function Ks(t){return(t=t||{}).datasets=t.datasets||[],t.labels=t.labels||[],t}const Gs=new Map,Zs=new Set;function Js(t,e){let i=Gs.get(t);return i||(i=e(),Gs.set(t,i),Zs.add(i)),i}const Qs=(t,e,i)=>{const s=ct(e,i);void 0!==s&&t.add(s)};class tn{constructor(t){this._config=function(t){return(t=t||{}).data=Ks(t.data),qs(t),t}(t),this._scopeCache=new Map,this._resolverCache=new Map}get platform(){return this._config.platform}get type(){return this._config.type}set type(t){this._config.type=t}get data(){return this._config.data}set data(t){this._config.data=Ks(t)}get options(){return this._config.options}set options(t){this._config.options=t}get plugins(){return this._config.plugins}update(){const t=this._config;this.clearCache(),qs(t)}clearCache(){this._scopeCache.clear(),this._resolverCache.clear()}datasetScopeKeys(t){return Js(t,(()=>[[`datasets.${t}`,""]]))}datasetAnimationScopeKeys(t,e){return Js(`${t}.transition.${e}`,(()=>[[`datasets.${t}.transitions.${e}`,`transitions.${e}`],[`datasets.${t}`,""]]))}datasetElementScopeKeys(t,e){return Js(`${t}-${e}`,(()=>[[`datasets.${t}.elements.${e}`,`datasets.${t}`,`elements.${e}`,""]]))}pluginScopeKeys(t){const e=t.id;return Js(`${this.type}-plugin-${e}`,(()=>[[`plugins.${e}`,...t.additionalOptionScopes||[]]]))}_cachedScopes(t,e){const i=this._scopeCache;let s=i.get(t);return s&&!e||(s=new Map,i.set(t,s)),s}getOptionScopes(t,e,i){const{options:s,type:n}=this,o=this._cachedScopes(t,i),a=o.get(e);if(a)return a;const r=new Set;e.forEach((e=>{t&&(r.add(t),e.forEach((e=>Qs(r,t,e)))),e.forEach((t=>Qs(r,s,t))),e.forEach((t=>Qs(r,mt[n]||{},t))),e.forEach((t=>Qs(r,yt,t))),e.forEach((t=>Qs(r,bt,t)))}));const l=Array.from(r);return 0===l.length&&l.push(Object.create(null)),Zs.has(e)&&o.set(e,l),l}chartOptionScopes(){const{options:t,type:e}=this;return[t,mt[e]||{},yt.datasets[e]||{},{type:e},yt,bt]}resolveNamedOptions(t,e,i,s=[""]){const n={$shared:!0},{resolver:o,subPrefixes:a}=en(this._resolverCache,t,s);let r=o;if(function(t,e){const{isScriptable:i,isIndexable:s}=Te(t);for(const n of e){const e=i(n),o=s(n),a=(o||e)&&t[n];if(e&&(ft(a)||sn(a))||o&&X(a))return!0}return!1}(o,e)){n.$shared=!1;r=Ae(o,i=ft(i)?i():i,this.createResolver(t,i,a))}for(const t of e)n[t]=r[t];return n}createResolver(t,e,i=[""],s){const{resolver:n}=en(this._resolverCache,t,i);return q(e)?Ae(n,e,void 0,s):n}}function en(t,e,i){let s=t.get(e);s||(s=new Map,t.set(e,s));const n=i.join();let o=s.get(n);if(!o){o={resolver:Oe(e,i),subPrefixes:i.filter((t=>!t.toLowerCase().includes("hover")))},s.set(n,o)}return o}const sn=t=>q(t)&&Object.getOwnPropertyNames(t).reduce(((e,i)=>e||ft(t[i])),!1);const nn=["top","bottom","left","right","chartArea"];function on(t,e){return"top"===t||"bottom"===t||-1===nn.indexOf(t)&&"x"===e}function an(t,e){return function(i,s){return i[t]===s[t]?i[e]-s[e]:i[t]-s[t]}}function rn(t){const e=t.chart,i=e.options.animation;e.notifyPlugins("afterRender"),tt(i&&i.onComplete,[t],e)}function ln(t){const e=t.chart,i=e.options.animation;tt(i&&i.onProgress,[t],e)}function hn(t){return ie()&&"string"==typeof t?t=document.getElementById(t):t&&t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas),t}const cn={},dn=t=>{const e=hn(t);return Object.values(cn).filter((t=>t.canvas===e)).pop()};function un(t,e,i){const s=Object.keys(t);for(const n of s){const s=+n;if(s>=e){const o=t[n];delete t[n],(i>0||s>e)&&(t[s+i]=o)}}}class fn{constructor(t,e){const s=this.config=new tn(e),n=hn(t),o=dn(n);if(o)throw new Error("Canvas is already in use. Chart with ID '"+o.id+"' must be destroyed before the canvas can be reused.");const r=s.createResolver(s.chartOptionScopes(),this.getContext());this.platform=new(s.platform||cs(n)),this.platform.updateConfig(s);const l=this.platform.acquireContext(n,r.aspectRatio),h=l&&l.canvas,c=h&&h.height,d=h&&h.width;this.id=Y(),this.ctx=l,this.canvas=h,this.width=d,this.height=c,this._options=r,this._aspectRatio=this.aspectRatio,this._layers=[],this._metasets=[],this._stacks=void 0,this.boxes=[],this.currentDevicePixelRatio=void 0,this.chartArea=void 0,this._active=[],this._lastEvent=void 0,this._listeners={},this._responsiveListeners=void 0,this._sortedMetasets=[],this.scales={},this._plugins=new js,this.$proxies={},this._hiddenIndices={},this.attached=!1,this._animationsDisabled=void 0,this.$context=void 0,this._doResize=i((t=>this.update(t)),r.resizeDelay||0),this._dataChanges=[],cn[this.id]=this,l&&h?(a.listen(this,"complete",rn),a.listen(this,"progress",ln),this._initialize(),this.attached&&this.update()):console.error("Failed to create chart: can't acquire context from the given item")}get aspectRatio(){const{options:{aspectRatio:t,maintainAspectRatio:e},width:i,height:s,_aspectRatio:n}=this;return U(t)?e&&n?n:s?i/s:null:t}get data(){return this.config.data}set data(t){this.config.data=t}get options(){return this._options}set options(t){this.config.options=t}_initialize(){return this.notifyPlugins("beforeInit"),this.options.responsive?this.resize():ue(this,this.options.devicePixelRatio),this.bindEvents(),this.notifyPlugins("afterInit"),this}clear(){return _e(this.canvas,this.ctx),this}stop(){return a.stop(this),this}resize(t,e){a.running(this)?this._resizeBeforeDraw={width:t,height:e}:this._resize(t,e)}_resize(t,e){const i=this.options,s=this.canvas,n=i.maintainAspectRatio&&this.aspectRatio,o=this.platform.getMaximumSize(s,t,e,n),a=i.devicePixelRatio||this.platform.getDevicePixelRatio(),r=this.width?"resize":"attach";this.width=o.width,this.height=o.height,this._aspectRatio=this.aspectRatio,ue(this,a,!0)&&(this.notifyPlugins("resize",{size:o}),tt(i.onResize,[this,o],this),this.attached&&this._doResize(r)&&this.render())}ensureScalesHaveIDs(){et(this.options.scales||{},((t,e)=>{t.id=e}))}buildOrUpdateScales(){const t=this.options,e=t.scales,i=this.scales,s=Object.keys(i).reduce(((t,e)=>(t[e]=!1,t)),{});let n=[];e&&(n=n.concat(Object.keys(e).map((t=>{const i=e[t],s=Xs(t,i),n="r"===s,o="x"===s;return{options:i,dposition:n?"chartArea":o?"bottom":"left",dtype:n?"radialLinear":o?"category":"linear"}})))),et(n,(e=>{const n=e.options,o=n.id,a=Xs(o,n),r=Z(n.type,e.dtype);void 0!==n.position&&on(n.position,a)===on(e.dposition)||(n.position=e.dposition),s[o]=!0;let l=null;if(o in i&&i[o].type===r)l=i[o];else{l=new(Hs.getScale(r))({id:o,type:r,ctx:this.ctx,chart:this}),i[l.id]=l}l.init(n,t)})),et(s,((t,e)=>{t||delete i[e]})),et(i,(t=>{Xi.configure(this,t,t.options),Xi.addBox(this,t)}))}_updateMetasets(){const t=this._metasets,e=this.data.datasets.length,i=t.length;if(t.sort(((t,e)=>t.index-e.index)),i>e){for(let t=e;t<i;++t)this._destroyDatasetMeta(t);t.splice(e,i-e)}this._sortedMetasets=t.slice(0).sort(an("order","index"))}_removeUnreferencedMetasets(){const{_metasets:t,data:{datasets:e}}=this;t.length>e.length&&delete this._stacks,t.forEach(((t,i)=>{0===e.filter((e=>e===t._dataset)).length&&this._destroyDatasetMeta(i)}))}buildOrUpdateControllers(){const t=[],e=this.data.datasets;let i,s;for(this._removeUnreferencedMetasets(),i=0,s=e.length;i<s;i++){const s=e[i];let n=this.getDatasetMeta(i);const o=s.type||this.config.type;if(n.type&&n.type!==o&&(this._destroyDatasetMeta(i),n=this.getDatasetMeta(i)),n.type=o,n.indexAxis=s.indexAxis||Us(o,this.options),n.order=s.order||0,n.index=i,n.label=""+s.label,n.visible=this.isDatasetVisible(i),n.controller)n.controller.updateIndex(i),n.controller.linkScales();else{const e=Hs.getController(o),{datasetElementType:s,dataElementType:a}=yt.datasets[o];Object.assign(e.prototype,{dataElementType:Hs.getElement(a),datasetElementType:s&&Hs.getElement(s)}),n.controller=new e(this,i),t.push(n.controller)}}return this._updateMetasets(),t}_resetElements(){et(this.data.datasets,((t,e)=>{this.getDatasetMeta(e).controller.reset()}),this)}reset(){this._resetElements(),this.notifyPlugins("reset")}update(t){const e=this.config;e.update();const i=this._options=e.createResolver(e.chartOptionScopes(),this.getContext()),s=this._animationsDisabled=!i.animation;if(this._updateScales(),this._checkEventBindings(),this._updateHiddenIndices(),this._plugins.invalidate(),!1===this.notifyPlugins("beforeUpdate",{mode:t,cancelable:!0}))return;const n=this.buildOrUpdateControllers();this.notifyPlugins("beforeElementsUpdate");let o=0;for(let t=0,e=this.data.datasets.length;t<e;t++){const{controller:e}=this.getDatasetMeta(t),i=!s&&-1===n.indexOf(e);e.buildOrUpdateElements(i),o=Math.max(+e.getMaxOverflow(),o)}o=this._minPadding=i.layout.autoPadding?o:0,this._updateLayout(o),s||et(n,(t=>{t.reset()})),this._updateDatasets(t),this.notifyPlugins("afterUpdate",{mode:t}),this._layers.sort(an("z","_idx"));const{_active:a,_lastEvent:r}=this;r?this._eventHandler(r,!0):a.length&&this._updateHoverStyles(a,a,!0),this.render()}_updateScales(){et(this.scales,(t=>{Xi.removeBox(this,t)})),this.ensureScalesHaveIDs(),this.buildOrUpdateScales()}_checkEventBindings(){const t=this.options,e=new Set(Object.keys(this._listeners)),i=new Set(t.events);gt(e,i)&&!!this._responsiveListeners===t.responsive||(this.unbindEvents(),this.bindEvents())}_updateHiddenIndices(){const{_hiddenIndices:t}=this,e=this._getUniformDataChanges()||[];for(const{method:i,start:s,count:n}of e){un(t,s,"_removeElements"===i?-n:n)}}_getUniformDataChanges(){const t=this._dataChanges;if(!t||!t.length)return;this._dataChanges=[];const e=this.data.datasets.length,i=e=>new Set(t.filter((t=>t[0]===e)).map(((t,e)=>e+","+t.splice(1).join(",")))),s=i(0);for(let t=1;t<e;t++)if(!gt(s,i(t)))return;return Array.from(s).map((t=>t.split(","))).map((t=>({method:t[1],start:+t[2],count:+t[3]})))}_updateLayout(t){if(!1===this.notifyPlugins("beforeLayout",{cancelable:!0}))return;Xi.update(this,this.width,this.height,t);const e=this.chartArea,i=e.width<=0||e.height<=0;this._layers=[],et(this.boxes,(t=>{i&&"chartArea"===t.position||(t.configure&&t.configure(),this._layers.push(...t._layers()))}),this),this._layers.forEach(((t,e)=>{t._idx=e})),this.notifyPlugins("afterLayout")}_updateDatasets(t){if(!1!==this.notifyPlugins("beforeDatasetsUpdate",{mode:t,cancelable:!0})){for(let t=0,e=this.data.datasets.length;t<e;++t)this.getDatasetMeta(t).controller.configure();for(let e=0,i=this.data.datasets.length;e<i;++e)this._updateDataset(e,ft(t)?t({datasetIndex:e}):t);this.notifyPlugins("afterDatasetsUpdate",{mode:t})}}_updateDataset(t,e){const i=this.getDatasetMeta(t),s={meta:i,index:t,mode:e,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetUpdate",s)&&(i.controller._update(e),s.cancelable=!1,this.notifyPlugins("afterDatasetUpdate",s))}render(){!1!==this.notifyPlugins("beforeRender",{cancelable:!0})&&(a.has(this)?this.attached&&!a.running(this)&&a.start(this):(this.draw(),rn({chart:this})))}draw(){let t;if(this._resizeBeforeDraw){const{width:t,height:e}=this._resizeBeforeDraw;this._resize(t,e),this._resizeBeforeDraw=null}if(this.clear(),this.width<=0||this.height<=0)return;if(!1===this.notifyPlugins("beforeDraw",{cancelable:!0}))return;const e=this._layers;for(t=0;t<e.length&&e[t].z<=0;++t)e[t].draw(this.chartArea);for(this._drawDatasets();t<e.length;++t)e[t].draw(this.chartArea);this.notifyPlugins("afterDraw")}_getSortedDatasetMetas(t){const e=this._sortedMetasets,i=[];let s,n;for(s=0,n=e.length;s<n;++s){const n=e[s];t&&!n.visible||i.push(n)}return i}getSortedVisibleDatasetMetas(){return this._getSortedDatasetMetas(!0)}_drawDatasets(){if(!1===this.notifyPlugins("beforeDatasetsDraw",{cancelable:!0}))return;const t=this.getSortedVisibleDatasetMetas();for(let e=t.length-1;e>=0;--e)this._drawDataset(t[e]);this.notifyPlugins("afterDatasetsDraw")}_drawDataset(t){const e=this.ctx,i=t._clip,s=!i.disabled,n=this.chartArea,o={meta:t,index:t.index,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetDraw",o)&&(s&&we(e,{left:!1===i.left?0:n.left-i.left,right:!1===i.right?this.width:n.right+i.right,top:!1===i.top?0:n.top-i.top,bottom:!1===i.bottom?this.height:n.bottom+i.bottom}),t.controller.draw(),s&&Me(e),o.cancelable=!1,this.notifyPlugins("afterDatasetDraw",o))}isPointInArea(t){return ve(t,this.chartArea,this._minPadding)}getElementsAtEventForMode(t,e,i,s){const n=Ei.modes[e];return"function"==typeof n?n(this,t,i,s):[]}getDatasetMeta(t){const e=this.data.datasets[t],i=this._metasets;let s=i.filter((t=>t&&t._dataset===e)).pop();return s||(s={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e&&e.order||0,index:t,_dataset:e,_parsed:[],_sorted:!1},i.push(s)),s}getContext(){return this.$context||(this.$context=pi(null,{chart:this,type:"chart"}))}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const e=this.data.datasets[t];if(!e)return!1;const i=this.getDatasetMeta(t);return"boolean"==typeof i.hidden?!i.hidden:!e.hidden}setDatasetVisibility(t,e){this.getDatasetMeta(t).hidden=!e}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateVisibility(t,e,i){const s=i?"show":"hide",n=this.getDatasetMeta(t),o=n.controller._resolveAnimations(void 0,s);ut(e)?(n.data[e].hidden=!i,this.update()):(this.setDatasetVisibility(t,i),o.update(n,{visible:i}),this.update((e=>e.datasetIndex===t?s:void 0)))}hide(t,e){this._updateVisibility(t,e,!1)}show(t,e){this._updateVisibility(t,e,!0)}_destroyDatasetMeta(t){const e=this._metasets[t];e&&e.controller&&e.controller._destroy(),delete this._metasets[t]}_stop(){let t,e;for(this.stop(),a.remove(this),t=0,e=this.data.datasets.length;t<e;++t)this._destroyDatasetMeta(t)}destroy(){this.notifyPlugins("beforeDestroy");const{canvas:t,ctx:e}=this;this._stop(),this.config.clearCache(),t&&(this.unbindEvents(),_e(t,e),this.platform.releaseContext(e),this.canvas=null,this.ctx=null),this.notifyPlugins("destroy"),delete cn[this.id],this.notifyPlugins("afterDestroy")}toBase64Image(...t){return this.canvas.toDataURL(...t)}bindEvents(){this.bindUserEvents(),this.options.responsive?this.bindResponsiveEvents():this.attached=!0}bindUserEvents(){const t=this._listeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(t,e,i)=>{t.offsetX=e,t.offsetY=i,this._eventHandler(t)};et(this.options.events,(t=>i(t,s)))}bindResponsiveEvents(){this._responsiveListeners||(this._responsiveListeners={});const t=this._responsiveListeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(i,s)=>{t[i]&&(e.removeEventListener(this,i,s),delete t[i])},n=(t,e)=>{this.canvas&&this.resize(t,e)};let o;const a=()=>{s("attach",a),this.attached=!0,this.resize(),i("resize",n),i("detach",o)};o=()=>{this.attached=!1,s("resize",n),this._stop(),this._resize(0,0),i("attach",a)},e.isAttached(this.canvas)?a():o()}unbindEvents(){et(this._listeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._listeners={},et(this._responsiveListeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._responsiveListeners=void 0}updateHoverStyle(t,e,i){const s=i?"set":"remove";let n,o,a,r;for("dataset"===e&&(n=this.getDatasetMeta(t[0].datasetIndex),n.controller["_"+s+"DatasetHoverStyle"]()),a=0,r=t.length;a<r;++a){o=t[a];const e=o&&this.getDatasetMeta(o.datasetIndex).controller;e&&e[s+"HoverStyle"](o.element,o.datasetIndex,o.index)}}getActiveElements(){return this._active||[]}setActiveElements(t){const e=this._active||[],i=t.map((({datasetIndex:t,index:e})=>{const i=this.getDatasetMeta(t);if(!i)throw new Error("No dataset found at index "+t);return{datasetIndex:t,element:i.data[e],index:e}}));!it(i,e)&&(this._active=i,this._lastEvent=null,this._updateHoverStyles(i,e))}notifyPlugins(t,e,i){return this._plugins.notify(this,t,e,i)}_updateHoverStyles(t,e,i){const s=this.options.hover,n=(t,e)=>t.filter((t=>!e.some((e=>t.datasetIndex===e.datasetIndex&&t.index===e.index)))),o=n(e,t),a=i?t:n(t,e);o.length&&this.updateHoverStyle(o,s.mode,!1),a.length&&s.mode&&this.updateHoverStyle(a,s.mode,!0)}_eventHandler(t,e){const i={event:t,replay:e,cancelable:!0,inChartArea:this.isPointInArea(t)},s=e=>(e.options.events||this.options.events).includes(t.native.type);if(!1===this.notifyPlugins("beforeEvent",i,s))return;const n=this._handleEvent(t,e,i.inChartArea);return i.cancelable=!1,this.notifyPlugins("afterEvent",i,s),(n||i.changed)&&this.render(),this}_handleEvent(t,e,i){const{_active:s=[],options:n}=this,o=e,a=this._getActiveElements(t,s,i,o),r=pt(t),l=function(t,e,i,s){return i&&"mouseout"!==t.type?s?e:t:null}(t,this._lastEvent,i,r);i&&(this._lastEvent=null,tt(n.onHover,[t,a,this],this),r&&tt(n.onClick,[t,a,this],this));const h=!it(a,s);return(h||e)&&(this._active=a,this._updateHoverStyles(a,s,e)),this._lastEvent=l,h}_getActiveElements(t,e,i,s){if("mouseout"===t.type)return[];if(!i)return e;const n=this.options.hover;return this.getElementsAtEventForMode(t,n.mode,n,s)}}const gn=()=>et(fn.instances,(t=>t._plugins.invalidate())),pn=!0;function mn(){throw new Error("This method is not implemented: Check that a complete date adapter is provided.")}Object.defineProperties(fn,{defaults:{enumerable:pn,value:yt},instances:{enumerable:pn,value:cn},overrides:{enumerable:pn,value:mt},registry:{enumerable:pn,value:Hs},version:{enumerable:pn,value:"3.8.0"},getChart:{enumerable:pn,value:dn},register:{enumerable:pn,value:(...t)=>{Hs.add(...t),gn()}},unregister:{enumerable:pn,value:(...t)=>{Hs.remove(...t),gn()}}});class bn{constructor(t){this.options=t||{}}formats(){return mn()}parse(t,e){return mn()}format(t,e){return mn()}add(t,e,i){return mn()}diff(t,e,i){return mn()}startOf(t,e,i){return mn()}endOf(t,e){return mn()}}bn.override=function(t){Object.assign(bn.prototype,t)};var xn={_date:bn};function _n(t){const e=t.iScale,i=function(t,e){if(!t._cache.$bar){const i=t.getMatchingVisibleMetas(e);let s=[];for(let e=0,n=i.length;e<n;e++)s=s.concat(i[e].controller.getAllParsedValues(t));t._cache.$bar=Ct(s.sort(((t,e)=>t-e)))}return t._cache.$bar}(e,t.type);let s,n,o,a,r=e._length;const l=()=>{32767!==o&&-32768!==o&&(ut(a)&&(r=Math.min(r,Math.abs(o-a)||r)),a=o)};for(s=0,n=i.length;s<n;++s)o=e.getPixelForValue(i[s]),l();for(a=void 0,s=0,n=e.ticks.length;s<n;++s)o=e.getPixelForTick(s),l();return r}function yn(t,e,i,s){return X(t)?function(t,e,i,s){const n=i.parse(t[0],s),o=i.parse(t[1],s),a=Math.min(n,o),r=Math.max(n,o);let l=a,h=r;Math.abs(a)>Math.abs(r)&&(l=r,h=a),e[i.axis]=h,e._custom={barStart:l,barEnd:h,start:n,end:o,min:a,max:r}}(t,e,i,s):e[i.axis]=i.parse(t,s),e}function vn(t,e,i,s){const n=t.iScale,o=t.vScale,a=n.getLabels(),r=n===o,l=[];let h,c,d,u;for(h=i,c=i+s;h<c;++h)u=e[h],d={},d[n.axis]=r||n.parse(a[h],h),l.push(yn(u,d,o,h));return l}function wn(t){return t&&void 0!==t.barStart&&void 0!==t.barEnd}function Mn(t,e,i,s){let n=e.borderSkipped;const o={};if(!n)return void(t.borderSkipped=o);const{start:a,end:r,reverse:l,top:h,bottom:c}=function(t){let e,i,s,n,o;return t.horizontal?(e=t.base>t.x,i="left",s="right"):(e=t.base<t.y,i="bottom",s="top"),e?(n="end",o="start"):(n="start",o="end"),{start:i,end:s,reverse:e,top:n,bottom:o}}(t);"middle"===n&&i&&(t.enableBorderRadius=!0,(i._top||0)===s?n=h:(i._bottom||0)===s?n=c:(o[kn(c,a,r,l)]=!0,n=h)),o[kn(n,a,r,l)]=!0,t.borderSkipped=o}function kn(t,e,i,s){var n,o,a;return s?(a=i,t=Sn(t=(n=t)===(o=e)?a:n===a?o:n,i,e)):t=Sn(t,e,i),t}function Sn(t,e,i){return"start"===t?e:"end"===t?i:t}function Pn(t,{inflateAmount:e},i){t.inflateAmount="auto"===e?1===i?.33:0:e}class Dn extends Cs{parsePrimitiveData(t,e,i,s){return vn(t,e,i,s)}parseArrayData(t,e,i,s){return vn(t,e,i,s)}parseObjectData(t,e,i,s){const{iScale:n,vScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l="x"===n.axis?a:r,h="x"===o.axis?a:r,c=[];let d,u,f,g;for(d=i,u=i+s;d<u;++d)g=e[d],f={},f[n.axis]=n.parse(ct(g,l),d),c.push(yn(ct(g,h),f,o,d));return c}updateRangeFromParsed(t,e,i,s){super.updateRangeFromParsed(t,e,i,s);const n=i._custom;n&&e===this._cachedMeta.vScale&&(t.min=Math.min(t.min,n.min),t.max=Math.max(t.max,n.max))}getMaxOverflow(){return 0}getLabelAndValue(t){const e=this._cachedMeta,{iScale:i,vScale:s}=e,n=this.getParsed(t),o=n._custom,a=wn(o)?"["+o.start+", "+o.end+"]":""+s.getLabelForValue(n[s.axis]);return{label:""+i.getLabelForValue(n[i.axis]),value:a}}initialize(){this.enableOptionSharing=!0,super.initialize();this._cachedMeta.stack=this.getDataset().stack}update(t){const e=this._cachedMeta;this.updateElements(e.data,0,e.data.length,t)}updateElements(t,e,i,s){const n="reset"===s,{index:o,_cachedMeta:{vScale:a}}=this,r=a.getBasePixel(),l=a.isHorizontal(),h=this._getRuler(),c=this.resolveDataElementOptions(e,s),d=this.getSharedOptions(c),u=this.includeOptions(s,d);this.updateSharedOptions(d,s,c);for(let c=e;c<e+i;c++){const e=this.getParsed(c),i=n||U(e[a.axis])?{base:r,head:r}:this._calculateBarValuePixels(c),f=this._calculateBarIndexPixels(c,h),g=(e._stacks||{})[a.axis],p={horizontal:l,base:i.base,enableBorderRadius:!g||wn(e._custom)||o===g._top||o===g._bottom,x:l?i.head:f.center,y:l?f.center:i.head,height:l?f.size:Math.abs(i.size),width:l?Math.abs(i.size):f.size};u&&(p.options=d||this.resolveDataElementOptions(c,t[c].active?"active":s));const m=p.options||t[c].options;Mn(p,m,g,o),Pn(p,m,h.ratio),this.updateElement(t[c],c,p,s)}}_getStacks(t,e){const i=this._cachedMeta.iScale,s=i.getMatchingVisibleMetas(this._type),n=i.options.stacked,o=s.length,a=[];let r,l;for(r=0;r<o;++r)if(l=s[r],l.controller.options.grouped){if(void 0!==e){const t=l.controller.getParsed(e)[l.controller._cachedMeta.vScale.axis];if(U(t)||isNaN(t))continue}if((!1===n||-1===a.indexOf(l.stack)||void 0===n&&void 0===l.stack)&&a.push(l.stack),l.index===t)break}return a.length||a.push(void 0),a}_getStackCount(t){return this._getStacks(void 0,t).length}_getStackIndex(t,e,i){const s=this._getStacks(t,i),n=void 0!==e?s.indexOf(e):-1;return-1===n?s.length-1:n}_getRuler(){const t=this.options,e=this._cachedMeta,i=e.iScale,s=[];let n,o;for(n=0,o=e.data.length;n<o;++n)s.push(i.getPixelForValue(this.getParsed(n)[i.axis],n));const a=t.barThickness;return{min:a||_n(e),pixels:s,start:i._startPixel,end:i._endPixel,stackCount:this._getStackCount(),scale:i,grouped:t.grouped,ratio:a?1:t.categoryPercentage*t.barPercentage}}_calculateBarValuePixels(t){const{_cachedMeta:{vScale:e,_stacked:i},options:{base:s,minBarLength:n}}=this,o=s||0,a=this.getParsed(t),r=a._custom,l=wn(r);let h,c,d=a[e.axis],u=0,f=i?this.applyStack(e,a,i):d;f!==d&&(u=f-d,f=d),l&&(d=r.barStart,f=r.barEnd-r.barStart,0!==d&&Bt(d)!==Bt(r.barEnd)&&(u=0),u+=d);const g=U(s)||l?u:s;let p=e.getPixelForValue(g);if(h=this.chart.getDataVisibility(t)?e.getPixelForValue(u+f):p,c=h-p,Math.abs(c)<n){c=function(t,e,i){return 0!==t?Bt(t):(e.isHorizontal()?1:-1)*(e.min>=i?1:-1)}(c,e,o)*n,d===o&&(p-=c/2);const t=e.getPixelForDecimal(0),i=e.getPixelForDecimal(1),s=Math.min(t,i),a=Math.max(t,i);p=Math.max(Math.min(p,a),s),h=p+c}if(p===e.getPixelForValue(o)){const t=Bt(c)*e.getLineWidthForValue(o)/2;p+=t,c-=t}return{size:c,base:p,head:h,center:h+c/2}}_calculateBarIndexPixels(t,e){const i=e.scale,s=this.options,n=s.skipNull,o=Z(s.maxBarThickness,1/0);let a,r;if(e.grouped){const i=n?this._getStackCount(t):e.stackCount,l="flex"===s.barThickness?function(t,e,i,s){const n=e.pixels,o=n[t];let a=t>0?n[t-1]:null,r=t<n.length-1?n[t+1]:null;const l=i.categoryPercentage;null===a&&(a=o-(null===r?e.end-e.start:r-o)),null===r&&(r=o+o-a);const h=o-(o-Math.min(a,r))/2*l;return{chunk:Math.abs(r-a)/2*l/s,ratio:i.barPercentage,start:h}}(t,e,s,i):function(t,e,i,s){const n=i.barThickness;let o,a;return U(n)?(o=e.min*i.categoryPercentage,a=i.barPercentage):(o=n*s,a=1),{chunk:o/s,ratio:a,start:e.pixels[t]-o/2}}(t,e,s,i),h=this._getStackIndex(this.index,this._cachedMeta.stack,n?t:void 0);a=l.start+l.chunk*h+l.chunk/2,r=Math.min(o,l.chunk*l.ratio)}else a=i.getPixelForValue(this.getParsed(t)[i.axis],t),r=Math.min(o,e.min*e.ratio);return{base:a-r/2,head:a+r/2,center:a,size:r}}draw(){const t=this._cachedMeta,e=t.vScale,i=t.data,s=i.length;let n=0;for(;n<s;++n)null!==this.getParsed(n)[e.axis]&&i[n].draw(this._ctx)}}Dn.id="bar",Dn.defaults={datasetElementType:!1,dataElementType:"bar",categoryPercentage:.8,barPercentage:.9,grouped:!0,animations:{numbers:{type:"number",properties:["x","y","base","width","height"]}}},Dn.overrides={scales:{_index_:{type:"category",offset:!0,grid:{offset:!0}},_value_:{type:"linear",beginAtZero:!0}}};class Cn extends Cs{initialize(){this.enableOptionSharing=!0,super.initialize()}parsePrimitiveData(t,e,i,s){const n=super.parsePrimitiveData(t,e,i,s);for(let t=0;t<n.length;t++)n[t]._custom=this.resolveDataElementOptions(t+i).radius;return n}parseArrayData(t,e,i,s){const n=super.parseArrayData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=Z(s[2],this.resolveDataElementOptions(t+i).radius)}return n}parseObjectData(t,e,i,s){const n=super.parseObjectData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=Z(s&&s.r&&+s.r,this.resolveDataElementOptions(t+i).radius)}return n}getMaxOverflow(){const t=this._cachedMeta.data;let e=0;for(let i=t.length-1;i>=0;--i)e=Math.max(e,t[i].size(this.resolveDataElementOptions(i))/2);return e>0&&e}getLabelAndValue(t){const e=this._cachedMeta,{xScale:i,yScale:s}=e,n=this.getParsed(t),o=i.getLabelForValue(n.x),a=s.getLabelForValue(n.y),r=n._custom;return{label:e.label,value:"("+o+", "+a+(r?", "+r:"")+")"}}update(t){const e=this._cachedMeta.data;this.updateElements(e,0,e.length,t)}updateElements(t,e,i,s){const n="reset"===s,{iScale:o,vScale:a}=this._cachedMeta,r=this.resolveDataElementOptions(e,s),l=this.getSharedOptions(r),h=this.includeOptions(s,l),c=o.axis,d=a.axis;for(let r=e;r<e+i;r++){const e=t[r],i=!n&&this.getParsed(r),l={},u=l[c]=n?o.getPixelForDecimal(.5):o.getPixelForValue(i[c]),f=l[d]=n?a.getBasePixel():a.getPixelForValue(i[d]);l.skip=isNaN(u)||isNaN(f),h&&(l.options=this.resolveDataElementOptions(r,e.active?"active":s),n&&(l.options.radius=0)),this.updateElement(e,r,l,s)}this.updateSharedOptions(l,s,r)}resolveDataElementOptions(t,e){const i=this.getParsed(t);let s=super.resolveDataElementOptions(t,e);s.$shared&&(s=Object.assign({},s,{$shared:!1}));const n=s.radius;return"active"!==e&&(s.radius=0),s.radius+=Z(i&&i._custom,n),s}}Cn.id="bubble",Cn.defaults={datasetElementType:!1,dataElementType:"point",animations:{numbers:{type:"number",properties:["x","y","borderWidth","radius"]}}},Cn.overrides={scales:{x:{type:"linear"},y:{type:"linear"}},plugins:{tooltip:{callbacks:{title:()=>""}}}};class On extends Cs{constructor(t,e){super(t,e),this.enableOptionSharing=!0,this.innerRadius=void 0,this.outerRadius=void 0,this.offsetX=void 0,this.offsetY=void 0}linkScales(){}parse(t,e){const i=this.getDataset().data,s=this._cachedMeta;if(!1===this._parsing)s._parsed=i;else{let n,o,a=t=>+i[t];if(q(i[t])){const{key:t="value"}=this._parsing;a=e=>+ct(i[e],t)}for(n=t,o=t+e;n<o;++n)s._parsed[n]=a(n)}}_getRotation(){return Yt(this.options.rotation-90)}_getCircumference(){return Yt(this.options.circumference)}_getRotationExtents(){let t=At,e=-At;for(let i=0;i<this.chart.data.datasets.length;++i)if(this.chart.isDatasetVisible(i)){const s=this.chart.getDatasetMeta(i).controller,n=s._getRotation(),o=s._getCircumference();t=Math.min(t,n),e=Math.max(e,n+o)}return{rotation:t,circumference:e-t}}update(t){const e=this.chart,{chartArea:i}=e,s=this._cachedMeta,n=s.data,o=this.getMaxBorderWidth()+this.getMaxOffset(n)+this.options.spacing,a=Math.max((Math.min(i.width,i.height)-o)/2,0),r=Math.min(J(this.options.cutout,a),1),l=this._getRingWeight(this.index),{circumference:h,rotation:c}=this._getRotationExtents(),{ratioX:d,ratioY:u,offsetX:f,offsetY:g}=function(t,e,i){let s=1,n=1,o=0,a=0;if(e<At){const r=t,l=r+e,h=Math.cos(r),c=Math.sin(r),d=Math.cos(l),u=Math.sin(l),f=(t,e,s)=>Jt(t,r,l,!0)?1:Math.max(e,e*i,s,s*i),g=(t,e,s)=>Jt(t,r,l,!0)?-1:Math.min(e,e*i,s,s*i),p=f(0,h,d),m=f(Et,c,u),b=g(Ot,h,d),x=g(Ot+Et,c,u);s=(p-b)/2,n=(m-x)/2,o=-(p+b)/2,a=-(m+x)/2}return{ratioX:s,ratioY:n,offsetX:o,offsetY:a}}(c,h,r),p=(i.width-o)/d,m=(i.height-o)/u,b=Math.max(Math.min(p,m)/2,0),x=Q(this.options.radius,b),_=(x-Math.max(x*r,0))/this._getVisibleDatasetWeightTotal();this.offsetX=f*x,this.offsetY=g*x,s.total=this.calculateTotal(),this.outerRadius=x-_*this._getRingWeightOffset(this.index),this.innerRadius=Math.max(this.outerRadius-_*l,0),this.updateElements(n,0,n.length,t)}_circumference(t,e){const i=this.options,s=this._cachedMeta,n=this._getCircumference();return e&&i.animation.animateRotate||!this.chart.getDataVisibility(t)||null===s._parsed[t]||s.data[t].hidden?0:this.calculateCircumference(s._parsed[t]*n/At)}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=o.chartArea,r=o.options.animation,l=(a.left+a.right)/2,h=(a.top+a.bottom)/2,c=n&&r.animateScale,d=c?0:this.innerRadius,u=c?0:this.outerRadius,f=this.resolveDataElementOptions(e,s),g=this.getSharedOptions(f),p=this.includeOptions(s,g);let m,b=this._getRotation();for(m=0;m<e;++m)b+=this._circumference(m,n);for(m=e;m<e+i;++m){const e=this._circumference(m,n),i=t[m],o={x:l+this.offsetX,y:h+this.offsetY,startAngle:b,endAngle:b+e,circumference:e,outerRadius:u,innerRadius:d};p&&(o.options=g||this.resolveDataElementOptions(m,i.active?"active":s)),b+=e,this.updateElement(i,m,o,s)}this.updateSharedOptions(g,s,f)}calculateTotal(){const t=this._cachedMeta,e=t.data;let i,s=0;for(i=0;i<e.length;i++){const n=t._parsed[i];null===n||isNaN(n)||!this.chart.getDataVisibility(i)||e[i].hidden||(s+=Math.abs(n))}return s}calculateCircumference(t){const e=this._cachedMeta.total;return e>0&&!isNaN(t)?At*(Math.abs(t)/e):0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=ni(e._parsed[t],i.options.locale);return{label:s[t]||"",value:n}}getMaxBorderWidth(t){let e=0;const i=this.chart;let s,n,o,a,r;if(!t)for(s=0,n=i.data.datasets.length;s<n;++s)if(i.isDatasetVisible(s)){o=i.getDatasetMeta(s),t=o.data,a=o.controller;break}if(!t)return 0;for(s=0,n=t.length;s<n;++s)r=a.resolveDataElementOptions(s),"inner"!==r.borderAlign&&(e=Math.max(e,r.borderWidth||0,r.hoverBorderWidth||0));return e}getMaxOffset(t){let e=0;for(let i=0,s=t.length;i<s;++i){const t=this.resolveDataElementOptions(i);e=Math.max(e,t.offset||0,t.hoverOffset||0)}return e}_getRingWeightOffset(t){let e=0;for(let i=0;i<t;++i)this.chart.isDatasetVisible(i)&&(e+=this._getRingWeight(i));return e}_getRingWeight(t){return Math.max(Z(this.chart.data.datasets[t].weight,1),0)}_getVisibleDatasetWeightTotal(){return this._getRingWeightOffset(this.chart.data.datasets.length)||1}}On.id="doughnut",On.defaults={datasetElementType:!1,dataElementType:"arc",animation:{animateRotate:!0,animateScale:!1},animations:{numbers:{type:"number",properties:["circumference","endAngle","innerRadius","outerRadius","startAngle","x","y","offset","borderWidth","spacing"]}},cutout:"50%",rotation:0,circumference:360,radius:"100%",spacing:0,indexAxis:"r"},On.descriptors={_scriptable:t=>"spacing"!==t,_indexable:t=>"spacing"!==t},On.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label(t){let e=t.label;const i=": "+t.formattedValue;return X(e)?(e=e.slice(),e[0]+=i):e+=i,e}}}}};class An extends Cs{initialize(){this.enableOptionSharing=!0,this.supportsDecimation=!0,super.initialize()}update(t){const e=this._cachedMeta,{dataset:i,data:s=[],_dataset:n}=e,o=this.chart._animationsDisabled;let{start:a,count:r}=function(t,e,i){const s=e.length;let n=0,o=s;if(t._sorted){const{iScale:a,_parsed:r}=t,l=a.axis,{min:h,max:c,minDefined:d,maxDefined:u}=a.getUserBounds();d&&(n=Qt(Math.min(wt(r,a.axis,h).lo,i?s:wt(e,l,a.getPixelForValue(h)).lo),0,s-1)),o=u?Qt(Math.max(wt(r,a.axis,c).hi+1,i?0:wt(e,l,a.getPixelForValue(c)).hi+1),n,s)-n:s-n}return{start:n,count:o}}(e,s,o);this._drawStart=a,this._drawCount=r,function(t){const{xScale:e,yScale:i,_scaleRanges:s}=t,n={xmin:e.min,xmax:e.max,ymin:i.min,ymax:i.max};if(!s)return t._scaleRanges=n,!0;const o=s.xmin!==e.min||s.xmax!==e.max||s.ymin!==i.min||s.ymax!==i.max;return Object.assign(s,n),o}(e)&&(a=0,r=s.length),i._chart=this.chart,i._datasetIndex=this.index,i._decimated=!!n._decimated,i.points=s;const l=this.resolveDatasetElementOptions(t);this.options.showLine||(l.borderWidth=0),l.segment=this.options.segment,this.updateElement(i,void 0,{animated:!o,options:l},t),this.updateElements(s,a,r,t)}updateElements(t,e,i,s){const n="reset"===s,{iScale:o,vScale:a,_stacked:r,_dataset:l}=this._cachedMeta,h=this.resolveDataElementOptions(e,s),c=this.getSharedOptions(h),d=this.includeOptions(s,c),u=o.axis,f=a.axis,{spanGaps:g,segment:p}=this.options,m=Wt(g)?g:Number.POSITIVE_INFINITY,b=this.chart._animationsDisabled||n||"none"===s;let x=e>0&&this.getParsed(e-1);for(let h=e;h<e+i;++h){const e=t[h],i=this.getParsed(h),g=b?e:{},_=U(i[f]),y=g[u]=o.getPixelForValue(i[u],h),v=g[f]=n||_?a.getBasePixel():a.getPixelForValue(r?this.applyStack(a,i,r):i[f],h);g.skip=isNaN(y)||isNaN(v)||_,g.stop=h>0&&Math.abs(i[u]-x[u])>m,p&&(g.parsed=i,g.raw=l.data[h]),d&&(g.options=c||this.resolveDataElementOptions(h,e.active?"active":s)),b||this.updateElement(e,h,g,s),x=i}this.updateSharedOptions(c,s,h)}getMaxOverflow(){const t=this._cachedMeta,e=t.dataset,i=e.options&&e.options.borderWidth||0,s=t.data||[];if(!s.length)return i;const n=s[0].size(this.resolveDataElementOptions(0)),o=s[s.length-1].size(this.resolveDataElementOptions(s.length-1));return Math.max(i,n,o)/2}draw(){const t=this._cachedMeta;t.dataset.updateControlPoints(this.chart.chartArea,t.iScale.axis),super.draw()}}An.id="line",An.defaults={datasetElementType:"line",dataElementType:"point",showLine:!0,spanGaps:!1},An.overrides={scales:{_index_:{type:"category"},_value_:{type:"linear"}}};class Tn extends Cs{constructor(t,e){super(t,e),this.innerRadius=void 0,this.outerRadius=void 0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=ni(e._parsed[t].r,i.options.locale);return{label:s[t]||"",value:n}}parseObjectData(t,e,i,s){return He.bind(this)(t,e,i,s)}update(t){const e=this._cachedMeta.data;this._updateRadius(),this.updateElements(e,0,e.length,t)}getMinMax(){const t=this._cachedMeta,e={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY};return t.data.forEach(((t,i)=>{const s=this.getParsed(i).r;!isNaN(s)&&this.chart.getDataVisibility(i)&&(s<e.min&&(e.min=s),s>e.max&&(e.max=s))})),e}_updateRadius(){const t=this.chart,e=t.chartArea,i=t.options,s=Math.min(e.right-e.left,e.bottom-e.top),n=Math.max(s/2,0),o=(n-Math.max(i.cutoutPercentage?n/100*i.cutoutPercentage:1,0))/t.getVisibleDatasetCount();this.outerRadius=n-o*this.index,this.innerRadius=this.outerRadius-o}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=o.options.animation,r=this._cachedMeta.rScale,l=r.xCenter,h=r.yCenter,c=r.getIndexAngle(0)-.5*Ot;let d,u=c;const f=360/this.countVisibleElements();for(d=0;d<e;++d)u+=this._computeAngle(d,s,f);for(d=e;d<e+i;d++){const e=t[d];let i=u,g=u+this._computeAngle(d,s,f),p=o.getDataVisibility(d)?r.getDistanceFromCenterForValue(this.getParsed(d).r):0;u=g,n&&(a.animateScale&&(p=0),a.animateRotate&&(i=g=c));const m={x:l,y:h,innerRadius:0,outerRadius:p,startAngle:i,endAngle:g,options:this.resolveDataElementOptions(d,e.active?"active":s)};this.updateElement(e,d,m,s)}}countVisibleElements(){const t=this._cachedMeta;let e=0;return t.data.forEach(((t,i)=>{!isNaN(this.getParsed(i).r)&&this.chart.getDataVisibility(i)&&e++})),e}_computeAngle(t,e,i){return this.chart.getDataVisibility(t)?Yt(this.resolveDataElementOptions(t,e).angle||i):0}}Tn.id="polarArea",Tn.defaults={dataElementType:"arc",animation:{animateRotate:!0,animateScale:!0},animations:{numbers:{type:"number",properties:["x","y","startAngle","endAngle","innerRadius","outerRadius"]}},indexAxis:"r",startAngle:0},Tn.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label:t=>t.chart.data.labels[t.dataIndex]+": "+t.formattedValue}}},scales:{r:{type:"radialLinear",angleLines:{display:!1},beginAtZero:!0,grid:{circular:!0},pointLabels:{display:!1},startAngle:0}}};class Ln extends On{}Ln.id="pie",Ln.defaults={cutout:0,rotation:0,circumference:360,radius:"100%"};class Rn extends Cs{getLabelAndValue(t){const e=this._cachedMeta.vScale,i=this.getParsed(t);return{label:e.getLabels()[t],value:""+e.getLabelForValue(i[e.axis])}}parseObjectData(t,e,i,s){return He.bind(this)(t,e,i,s)}update(t){const e=this._cachedMeta,i=e.dataset,s=e.data||[],n=e.iScale.getLabels();if(i.points=s,"resize"!==t){const e=this.resolveDatasetElementOptions(t);this.options.showLine||(e.borderWidth=0);const o={_loop:!0,_fullLoop:n.length===s.length,options:e};this.updateElement(i,void 0,o,t)}this.updateElements(s,0,s.length,t)}updateElements(t,e,i,s){const n=this._cachedMeta.rScale,o="reset"===s;for(let a=e;a<e+i;a++){const e=t[a],i=this.resolveDataElementOptions(a,e.active?"active":s),r=n.getPointPositionForValue(a,this.getParsed(a).r),l=o?n.xCenter:r.x,h=o?n.yCenter:r.y,c={x:l,y:h,angle:r.angle,skip:isNaN(l)||isNaN(h),options:i};this.updateElement(e,a,c,s)}}}Rn.id="radar",Rn.defaults={datasetElementType:"line",dataElementType:"point",indexAxis:"r",showLine:!0,elements:{line:{fill:"start"}}},Rn.overrides={aspectRatio:1,scales:{r:{type:"radialLinear"}}};class En extends An{}En.id="scatter",En.defaults={showLine:!1,fill:!1},En.overrides={interaction:{mode:"point"},plugins:{tooltip:{callbacks:{title:()=>"",label:t=>"("+t.label+", "+t.formattedValue+")"}}},scales:{x:{type:"linear"},y:{type:"linear"}}};var In=Object.freeze({__proto__:null,BarController:Dn,BubbleController:Cn,DoughnutController:On,LineController:An,PolarAreaController:Tn,PieController:Ln,RadarController:Rn,ScatterController:En});function zn(t,e,i){const{startAngle:s,pixelMargin:n,x:o,y:a,outerRadius:r,innerRadius:l}=e;let h=n/r;t.beginPath(),t.arc(o,a,r,s-h,i+h),l>n?(h=n/l,t.arc(o,a,l,i+h,s-h,!0)):t.arc(o,a,n,i+Et,s-Et),t.closePath(),t.clip()}function Fn(t,e,i,s){const n=li(t.options.borderRadius,["outerStart","outerEnd","innerStart","innerEnd"]);const o=(i-e)/2,a=Math.min(o,s*e/2),r=t=>{const e=(i-Math.min(o,t))*s/2;return Qt(t,0,Math.min(o,e))};return{outerStart:r(n.outerStart),outerEnd:r(n.outerEnd),innerStart:Qt(n.innerStart,0,a),innerEnd:Qt(n.innerEnd,0,a)}}function Bn(t,e,i,s){return{x:i+t*Math.cos(e),y:s+t*Math.sin(e)}}function Vn(t,e,i,s,n){const{x:o,y:a,startAngle:r,pixelMargin:l,innerRadius:h}=e,c=Math.max(e.outerRadius+s+i-l,0),d=h>0?h+s+i+l:0;let u=0;const f=n-r;if(s){const t=((h>0?h-s:0)+(c>0?c-s:0))/2;u=(f-(0!==t?f*t/(t+s):f))/2}const g=(f-Math.max(.001,f*c-i/Ot)/c)/2,p=r+g+u,m=n-g-u,{outerStart:b,outerEnd:x,innerStart:_,innerEnd:y}=Fn(e,d,c,m-p),v=c-b,w=c-x,M=p+b/v,k=m-x/w,S=d+_,P=d+y,D=p+_/S,C=m-y/P;if(t.beginPath(),t.arc(o,a,c,M,k),x>0){const e=Bn(w,k,o,a);t.arc(e.x,e.y,x,k,m+Et)}const O=Bn(P,m,o,a);if(t.lineTo(O.x,O.y),y>0){const e=Bn(P,C,o,a);t.arc(e.x,e.y,y,m+Et,C+Math.PI)}if(t.arc(o,a,d,m-y/d,p+_/d,!0),_>0){const e=Bn(S,D,o,a);t.arc(e.x,e.y,_,D+Math.PI,p-Et)}const A=Bn(v,p,o,a);if(t.lineTo(A.x,A.y),b>0){const e=Bn(v,M,o,a);t.arc(e.x,e.y,b,p-Et,M)}t.closePath()}function Nn(t,e,i,s,n){const{options:o}=e,{borderWidth:a,borderJoinStyle:r}=o,l="inner"===o.borderAlign;a&&(l?(t.lineWidth=2*a,t.lineJoin=r||"round"):(t.lineWidth=a,t.lineJoin=r||"bevel"),e.fullCircles&&function(t,e,i){const{x:s,y:n,startAngle:o,pixelMargin:a,fullCircles:r}=e,l=Math.max(e.outerRadius-a,0),h=e.innerRadius+a;let c;for(i&&zn(t,e,o+At),t.beginPath(),t.arc(s,n,h,o+At,o,!0),c=0;c<r;++c)t.stroke();for(t.beginPath(),t.arc(s,n,l,o,o+At),c=0;c<r;++c)t.stroke()}(t,e,l),l&&zn(t,e,n),Vn(t,e,i,s,n),t.stroke())}class Wn extends Os{constructor(t){super(),this.options=void 0,this.circumference=void 0,this.startAngle=void 0,this.endAngle=void 0,this.innerRadius=void 0,this.outerRadius=void 0,this.pixelMargin=0,this.fullCircles=0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.getProps(["x","y"],i),{angle:n,distance:o}=qt(s,{x:t,y:e}),{startAngle:a,endAngle:r,innerRadius:l,outerRadius:h,circumference:c}=this.getProps(["startAngle","endAngle","innerRadius","outerRadius","circumference"],i),d=this.options.spacing/2,u=Z(c,r-a)>=At||Jt(n,a,r),f=ee(o,l+d,h+d);return u&&f}getCenterPoint(t){const{x:e,y:i,startAngle:s,endAngle:n,innerRadius:o,outerRadius:a}=this.getProps(["x","y","startAngle","endAngle","innerRadius","outerRadius","circumference"],t),{offset:r,spacing:l}=this.options,h=(s+n)/2,c=(o+a+l+r)/2;return{x:e+Math.cos(h)*c,y:i+Math.sin(h)*c}}tooltipPosition(t){return this.getCenterPoint(t)}draw(t){const{options:e,circumference:i}=this,s=(e.offset||0)/2,n=(e.spacing||0)/2;if(this.pixelMargin="inner"===e.borderAlign?.33:0,this.fullCircles=i>At?Math.floor(i/At):0,0===i||this.innerRadius<0||this.outerRadius<0)return;t.save();let o=0;if(s){o=s/2;const e=(this.startAngle+this.endAngle)/2;t.translate(Math.cos(e)*o,Math.sin(e)*o),this.circumference>=Ot&&(o=s)}t.fillStyle=e.backgroundColor,t.strokeStyle=e.borderColor;const a=function(t,e,i,s){const{fullCircles:n,startAngle:o,circumference:a}=e;let r=e.endAngle;if(n){Vn(t,e,i,s,o+At);for(let e=0;e<n;++e)t.fill();isNaN(a)||(r=o+a%At,a%At==0&&(r+=At))}return Vn(t,e,i,s,r),t.fill(),r}(t,this,o,n);Nn(t,this,o,n,a),t.restore()}}function Hn(t,e,i=e){t.lineCap=Z(i.borderCapStyle,e.borderCapStyle),t.setLineDash(Z(i.borderDash,e.borderDash)),t.lineDashOffset=Z(i.borderDashOffset,e.borderDashOffset),t.lineJoin=Z(i.borderJoinStyle,e.borderJoinStyle),t.lineWidth=Z(i.borderWidth,e.borderWidth),t.strokeStyle=Z(i.borderColor,e.borderColor)}function jn(t,e,i){t.lineTo(i.x,i.y)}function $n(t,e,i={}){const s=t.length,{start:n=0,end:o=s-1}=i,{start:a,end:r}=e,l=Math.max(n,a),h=Math.min(o,r),c=n<a&&o<a||n>r&&o>r;return{count:s,start:l,loop:e.loop,ilen:h<l&&!c?s+h-l:h-l}}function Yn(t,e,i,s){const{points:n,options:o}=e,{count:a,start:r,loop:l,ilen:h}=$n(n,i,s),c=function(t){return t.stepped?ke:t.tension||"monotone"===t.cubicInterpolationMode?Se:jn}(o);let d,u,f,{move:g=!0,reverse:p}=s||{};for(d=0;d<=h;++d)u=n[(r+(p?h-d:d))%a],u.skip||(g?(t.moveTo(u.x,u.y),g=!1):c(t,f,u,p,o.stepped),f=u);return l&&(u=n[(r+(p?h:0))%a],c(t,f,u,p,o.stepped)),!!l}function Un(t,e,i,s){const n=e.points,{count:o,start:a,ilen:r}=$n(n,i,s),{move:l=!0,reverse:h}=s||{};let c,d,u,f,g,p,m=0,b=0;const x=t=>(a+(h?r-t:t))%o,_=()=>{f!==g&&(t.lineTo(m,g),t.lineTo(m,f),t.lineTo(m,p))};for(l&&(d=n[x(0)],t.moveTo(d.x,d.y)),c=0;c<=r;++c){if(d=n[x(c)],d.skip)continue;const e=d.x,i=d.y,s=0|e;s===u?(i<f?f=i:i>g&&(g=i),m=(b*m+e)/++b):(_(),t.lineTo(e,i),u=s,b=0,f=g=i),p=i}_()}function Xn(t){const e=t.options,i=e.borderDash&&e.borderDash.length;return!(t._decimated||t._loop||e.tension||"monotone"===e.cubicInterpolationMode||e.stepped||i)?Un:Yn}Wn.id="arc",Wn.defaults={borderAlign:"center",borderColor:"#fff",borderJoinStyle:void 0,borderRadius:0,borderWidth:2,offset:0,spacing:0,angle:void 0},Wn.defaultRoutes={backgroundColor:"backgroundColor"};const qn="function"==typeof Path2D;function Kn(t,e,i,s){qn&&!e.options.segment?function(t,e,i,s){let n=e._path;n||(n=e._path=new Path2D,e.path(n,i,s)&&n.closePath()),Hn(t,e.options),t.stroke(n)}(t,e,i,s):function(t,e,i,s){const{segments:n,options:o}=e,a=Xn(e);for(const r of n)Hn(t,o,r.style),t.beginPath(),a(t,e,r,{start:i,end:i+s-1})&&t.closePath(),t.stroke()}(t,e,i,s)}class Gn extends Os{constructor(t){super(),this.animated=!0,this.options=void 0,this._chart=void 0,this._loop=void 0,this._fullLoop=void 0,this._path=void 0,this._points=void 0,this._segments=void 0,this._decimated=!1,this._pointsUpdated=!1,this._datasetIndex=void 0,t&&Object.assign(this,t)}updateControlPoints(t,e){const i=this.options;if((i.tension||"monotone"===i.cubicInterpolationMode)&&!i.stepped&&!this._pointsUpdated){const s=i.spanGaps?this._loop:this._fullLoop;Ke(this._points,i,t,s,e),this._pointsUpdated=!0}}set points(t){this._points=t,delete this._segments,delete this._path,this._pointsUpdated=!1}get points(){return this._points}get segments(){return this._segments||(this._segments=Mi(this,this.options.segment))}first(){const t=this.segments,e=this.points;return t.length&&e[t[0].start]}last(){const t=this.segments,e=this.points,i=t.length;return i&&e[t[i-1].end]}interpolate(t,e){const i=this.options,s=t[e],n=this.points,o=wi(this,{property:e,start:s,end:s});if(!o.length)return;const a=[],r=function(t){return t.stepped?ei:t.tension||"monotone"===t.cubicInterpolationMode?ii:ti}(i);let l,h;for(l=0,h=o.length;l<h;++l){const{start:h,end:c}=o[l],d=n[h],u=n[c];if(d===u){a.push(d);continue}const f=r(d,u,Math.abs((s-d[e])/(u[e]-d[e])),i.stepped);f[e]=t[e],a.push(f)}return 1===a.length?a[0]:a}pathSegment(t,e,i){return Xn(this)(t,this,e,i)}path(t,e,i){const s=this.segments,n=Xn(this);let o=this._loop;e=e||0,i=i||this.points.length-e;for(const a of s)o&=n(t,this,a,{start:e,end:e+i-1});return!!o}draw(t,e,i,s){const n=this.options||{};(this.points||[]).length&&n.borderWidth&&(t.save(),Kn(t,this,i,s),t.restore()),this.animated&&(this._pointsUpdated=!1,this._path=void 0)}}function Zn(t,e,i,s){const n=t.options,{[i]:o}=t.getProps([i],s);return Math.abs(e-o)<n.radius+n.hitRadius}Gn.id="line",Gn.defaults={borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderWidth:3,capBezierPoints:!0,cubicInterpolationMode:"default",fill:!1,spanGaps:!1,stepped:!1,tension:0},Gn.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"},Gn.descriptors={_scriptable:!0,_indexable:t=>"borderDash"!==t&&"fill"!==t};class Jn extends Os{constructor(t){super(),this.options=void 0,this.parsed=void 0,this.skip=void 0,this.stop=void 0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.options,{x:n,y:o}=this.getProps(["x","y"],i);return Math.pow(t-n,2)+Math.pow(e-o,2)<Math.pow(s.hitRadius+s.radius,2)}inXRange(t,e){return Zn(this,t,"x",e)}inYRange(t,e){return Zn(this,t,"y",e)}getCenterPoint(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}size(t){let e=(t=t||this.options||{}).radius||0;e=Math.max(e,e&&t.hoverRadius||0);return 2*(e+(e&&t.borderWidth||0))}draw(t,e){const i=this.options;this.skip||i.radius<.1||!ve(this,e,this.size(i)/2)||(t.strokeStyle=i.borderColor,t.lineWidth=i.borderWidth,t.fillStyle=i.backgroundColor,ye(t,i,this.x,this.y))}getRange(){const t=this.options||{};return t.radius+t.hitRadius}}function Qn(t,e){const{x:i,y:s,base:n,width:o,height:a}=t.getProps(["x","y","base","width","height"],e);let r,l,h,c,d;return t.horizontal?(d=a/2,r=Math.min(i,n),l=Math.max(i,n),h=s-d,c=s+d):(d=o/2,r=i-d,l=i+d,h=Math.min(s,n),c=Math.max(s,n)),{left:r,top:h,right:l,bottom:c}}function to(t,e,i,s){return t?0:Qt(e,i,s)}function eo(t){const e=Qn(t),i=e.right-e.left,s=e.bottom-e.top,n=function(t,e,i){const s=t.options.borderWidth,n=t.borderSkipped,o=hi(s);return{t:to(n.top,o.top,0,i),r:to(n.right,o.right,0,e),b:to(n.bottom,o.bottom,0,i),l:to(n.left,o.left,0,e)}}(t,i/2,s/2),o=function(t,e,i){const{enableBorderRadius:s}=t.getProps(["enableBorderRadius"]),n=t.options.borderRadius,o=ci(n),a=Math.min(e,i),r=t.borderSkipped,l=s||q(n);return{topLeft:to(!l||r.top||r.left,o.topLeft,0,a),topRight:to(!l||r.top||r.right,o.topRight,0,a),bottomLeft:to(!l||r.bottom||r.left,o.bottomLeft,0,a),bottomRight:to(!l||r.bottom||r.right,o.bottomRight,0,a)}}(t,i/2,s/2);return{outer:{x:e.left,y:e.top,w:i,h:s,radius:o},inner:{x:e.left+n.l,y:e.top+n.t,w:i-n.l-n.r,h:s-n.t-n.b,radius:{topLeft:Math.max(0,o.topLeft-Math.max(n.t,n.l)),topRight:Math.max(0,o.topRight-Math.max(n.t,n.r)),bottomLeft:Math.max(0,o.bottomLeft-Math.max(n.b,n.l)),bottomRight:Math.max(0,o.bottomRight-Math.max(n.b,n.r))}}}}function io(t,e,i,s){const n=null===e,o=null===i,a=t&&!(n&&o)&&Qn(t,s);return a&&(n||ee(e,a.left,a.right))&&(o||ee(i,a.top,a.bottom))}function so(t,e){t.rect(e.x,e.y,e.w,e.h)}function no(t,e,i={}){const s=t.x!==i.x?-e:0,n=t.y!==i.y?-e:0,o=(t.x+t.w!==i.x+i.w?e:0)-s,a=(t.y+t.h!==i.y+i.h?e:0)-n;return{x:t.x+s,y:t.y+n,w:t.w+o,h:t.h+a,radius:t.radius}}Jn.id="point",Jn.defaults={borderWidth:1,hitRadius:1,hoverBorderWidth:1,hoverRadius:4,pointStyle:"circle",radius:3,rotation:0},Jn.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};class oo extends Os{constructor(t){super(),this.options=void 0,this.horizontal=void 0,this.base=void 0,this.width=void 0,this.height=void 0,this.inflateAmount=void 0,t&&Object.assign(this,t)}draw(t){const{inflateAmount:e,options:{borderColor:i,backgroundColor:s}}=this,{inner:n,outer:o}=eo(this),a=(r=o.radius).topLeft||r.topRight||r.bottomLeft||r.bottomRight?Ce:so;var r;t.save(),o.w===n.w&&o.h===n.h||(t.beginPath(),a(t,no(o,e,n)),t.clip(),a(t,no(n,-e,o)),t.fillStyle=i,t.fill("evenodd")),t.beginPath(),a(t,no(n,e)),t.fillStyle=s,t.fill(),t.restore()}inRange(t,e,i){return io(this,t,e,i)}inXRange(t,e){return io(this,t,null,e)}inYRange(t,e){return io(this,null,t,e)}getCenterPoint(t){const{x:e,y:i,base:s,horizontal:n}=this.getProps(["x","y","base","horizontal"],t);return{x:n?(e+s)/2:e,y:n?i:(i+s)/2}}getRange(t){return"x"===t?this.width/2:this.height/2}}oo.id="bar",oo.defaults={borderSkipped:"start",borderWidth:0,borderRadius:0,inflateAmount:"auto",pointStyle:void 0},oo.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};var ao=Object.freeze({__proto__:null,ArcElement:Wn,LineElement:Gn,PointElement:Jn,BarElement:oo});function ro(t){if(t._decimated){const e=t._data;delete t._decimated,delete t._data,Object.defineProperty(t,"data",{value:e})}}function lo(t){t.data.datasets.forEach((t=>{ro(t)}))}var ho={id:"decimation",defaults:{algorithm:"min-max",enabled:!1},beforeElementsUpdate:(t,e,i)=>{if(!i.enabled)return void lo(t);const s=t.width;t.data.datasets.forEach(((e,n)=>{const{_data:o,indexAxis:a}=e,r=t.getDatasetMeta(n),l=o||e.data;if("y"===fi([a,t.options.indexAxis]))return;if(!r.controller.supportsDecimation)return;const h=t.scales[r.xAxisID];if("linear"!==h.type&&"time"!==h.type)return;if(t.options.parsing)return;let{start:c,count:d}=function(t,e){const i=e.length;let s,n=0;const{iScale:o}=t,{min:a,max:r,minDefined:l,maxDefined:h}=o.getUserBounds();return l&&(n=Qt(wt(e,o.axis,a).lo,0,i-1)),s=h?Qt(wt(e,o.axis,r).hi+1,n,i)-n:i-n,{start:n,count:s}}(r,l);if(d<=(i.threshold||4*s))return void ro(e);let u;switch(U(o)&&(e._data=l,delete e.data,Object.defineProperty(e,"data",{configurable:!0,enumerable:!0,get:function(){return this._decimated},set:function(t){this._data=t}})),i.algorithm){case"lttb":u=function(t,e,i,s,n){const o=n.samples||s;if(o>=i)return t.slice(e,e+i);const a=[],r=(i-2)/(o-2);let l=0;const h=e+i-1;let c,d,u,f,g,p=e;for(a[l++]=t[p],c=0;c<o-2;c++){let s,n=0,o=0;const h=Math.floor((c+1)*r)+1+e,m=Math.min(Math.floor((c+2)*r)+1,i)+e,b=m-h;for(s=h;s<m;s++)n+=t[s].x,o+=t[s].y;n/=b,o/=b;const x=Math.floor(c*r)+1+e,_=Math.min(Math.floor((c+1)*r)+1,i)+e,{x:y,y:v}=t[p];for(u=f=-1,s=x;s<_;s++)f=.5*Math.abs((y-n)*(t[s].y-v)-(y-t[s].x)*(o-v)),f>u&&(u=f,d=t[s],g=s);a[l++]=d,p=g}return a[l++]=t[h],a}(l,c,d,s,i);break;case"min-max":u=function(t,e,i,s){let n,o,a,r,l,h,c,d,u,f,g=0,p=0;const m=[],b=e+i-1,x=t[e].x,_=t[b].x-x;for(n=e;n<e+i;++n){o=t[n],a=(o.x-x)/_*s,r=o.y;const e=0|a;if(e===l)r<u?(u=r,h=n):r>f&&(f=r,c=n),g=(p*g+o.x)/++p;else{const i=n-1;if(!U(h)&&!U(c)){const e=Math.min(h,c),s=Math.max(h,c);e!==d&&e!==i&&m.push({...t[e],x:g}),s!==d&&s!==i&&m.push({...t[s],x:g})}n>0&&i!==d&&m.push(t[i]),m.push(o),l=e,p=0,u=f=r,h=c=d=n}}return m}(l,c,d,s);break;default:throw new Error(`Unsupported decimation algorithm '${i.algorithm}'`)}e._decimated=u}))},destroy(t){lo(t)}};function co(t,e,i,s){if(s)return;let n=e[t],o=i[t];return"angle"===t&&(n=Zt(n),o=Zt(o)),{property:t,start:n,end:o}}function uo(t,e,i){for(;e>t;e--){const t=i[e];if(!isNaN(t.x)&&!isNaN(t.y))break}return e}function fo(t,e,i,s){return t&&e?s(t[i],e[i]):t?t[i]:e?e[i]:0}function go(t,e){let i=[],s=!1;return X(t)?(s=!0,i=t):i=function(t,e){const{x:i=null,y:s=null}=t||{},n=e.points,o=[];return e.segments.forEach((({start:t,end:e})=>{e=uo(t,e,n);const a=n[t],r=n[e];null!==s?(o.push({x:a.x,y:s}),o.push({x:r.x,y:s})):null!==i&&(o.push({x:i,y:a.y}),o.push({x:i,y:r.y}))})),o}(t,e),i.length?new Gn({points:i,options:{tension:0},_loop:s,_fullLoop:s}):null}function po(t,e,i){let s=t[e].fill;const n=[e];let o;if(!i)return s;for(;!1!==s&&-1===n.indexOf(s);){if(!K(s))return s;if(o=t[s],!o)return!1;if(o.visible)return s;n.push(s),s=o.fill}return!1}function mo(t,e,i){const s=function(t){const e=t.options,i=e.fill;let s=Z(i&&i.target,i);void 0===s&&(s=!!e.backgroundColor);if(!1===s||null===s)return!1;if(!0===s)return"origin";return s}(t);if(q(s))return!isNaN(s.value)&&s;let n=parseFloat(s);return K(n)&&Math.floor(n)===n?function(t,e,i,s){"-"!==t&&"+"!==t||(i=e+i);if(i===e||i<0||i>=s)return!1;return i}(s[0],e,n,i):["origin","start","end","stack","shape"].indexOf(s)>=0&&s}function bo(t,e,i){const s=[];for(let n=0;n<i.length;n++){const o=i[n],{first:a,last:r,point:l}=xo(o,e,"x");if(!(!l||a&&r))if(a)s.unshift(l);else if(t.push(l),!r)break}t.push(...s)}function xo(t,e,i){const s=t.interpolate(e,i);if(!s)return{};const n=s[i],o=t.segments,a=t.points;let r=!1,l=!1;for(let t=0;t<o.length;t++){const e=o[t],s=a[e.start][i],h=a[e.end][i];if(ee(n,s,h)){r=n===s,l=n===h;break}}return{first:r,last:l,point:s}}class _o{constructor(t){this.x=t.x,this.y=t.y,this.radius=t.radius}pathSegment(t,e,i){const{x:s,y:n,radius:o}=this;return e=e||{start:0,end:At},t.arc(s,n,o,e.end,e.start,!0),!i.bounds}interpolate(t){const{x:e,y:i,radius:s}=this,n=t.angle;return{x:e+Math.cos(n)*s,y:i+Math.sin(n)*s,angle:n}}}function yo(t){const{chart:e,fill:i,line:s}=t;if(K(i))return function(t,e){const i=t.getDatasetMeta(e);return i&&t.isDatasetVisible(e)?i.dataset:null}(e,i);if("stack"===i)return function(t){const{scale:e,index:i,line:s}=t,n=[],o=s.segments,a=s.points,r=function(t,e){const i=[],s=t.getMatchingVisibleMetas("line");for(let t=0;t<s.length;t++){const n=s[t];if(n.index===e)break;n.hidden||i.unshift(n.dataset)}return i}(e,i);r.push(go({x:null,y:e.bottom},s));for(let t=0;t<o.length;t++){const e=o[t];for(let t=e.start;t<=e.end;t++)bo(n,a[t],r)}return new Gn({points:n,options:{}})}(t);if("shape"===i)return!0;const n=function(t){if((t.scale||{}).getPointPositionForValue)return function(t){const{scale:e,fill:i}=t,s=e.options,n=e.getLabels().length,o=s.reverse?e.max:e.min,a=function(t,e,i){let s;return s="start"===t?i:"end"===t?e.options.reverse?e.min:e.max:q(t)?t.value:e.getBaseValue(),s}(i,e,o),r=[];if(s.grid.circular){const t=e.getPointPositionForValue(0,o);return new _o({x:t.x,y:t.y,radius:e.getDistanceFromCenterForValue(a)})}for(let t=0;t<n;++t)r.push(e.getPointPositionForValue(t,a));return r}(t);return function(t){const{scale:e={},fill:i}=t,s=function(t,e){let i=null;return"start"===t?i=e.bottom:"end"===t?i=e.top:q(t)?i=e.getPixelForValue(t.value):e.getBasePixel&&(i=e.getBasePixel()),i}(i,e);if(K(s)){const t=e.isHorizontal();return{x:t?s:null,y:t?null:s}}return null}(t)}(t);return n instanceof _o?n:go(n,s)}function vo(t,e,i){const s=yo(e),{line:n,scale:o,axis:a}=e,r=n.options,l=r.fill,h=r.backgroundColor,{above:c=h,below:d=h}=l||{};s&&n.points.length&&(we(t,i),function(t,e){const{line:i,target:s,above:n,below:o,area:a,scale:r}=e,l=i._loop?"angle":e.axis;t.save(),"x"===l&&o!==n&&(wo(t,s,a.top),Mo(t,{line:i,target:s,color:n,scale:r,property:l}),t.restore(),t.save(),wo(t,s,a.bottom));Mo(t,{line:i,target:s,color:o,scale:r,property:l}),t.restore()}(t,{line:n,target:s,above:c,below:d,area:i,scale:o,axis:a}),Me(t))}function wo(t,e,i){const{segments:s,points:n}=e;let o=!0,a=!1;t.beginPath();for(const r of s){const{start:s,end:l}=r,h=n[s],c=n[uo(s,l,n)];o?(t.moveTo(h.x,h.y),o=!1):(t.lineTo(h.x,i),t.lineTo(h.x,h.y)),a=!!e.pathSegment(t,r,{move:a}),a?t.closePath():t.lineTo(c.x,i)}t.lineTo(e.first().x,i),t.closePath(),t.clip()}function Mo(t,e){const{line:i,target:s,property:n,color:o,scale:a}=e,r=function(t,e,i){const s=t.segments,n=t.points,o=e.points,a=[];for(const t of s){let{start:s,end:r}=t;r=uo(s,r,n);const l=co(i,n[s],n[r],t.loop);if(!e.segments){a.push({source:t,target:l,start:n[s],end:n[r]});continue}const h=wi(e,l);for(const e of h){const s=co(i,o[e.start],o[e.end],e.loop),r=vi(t,n,s);for(const t of r)a.push({source:t,target:e,start:{[i]:fo(l,s,"start",Math.max)},end:{[i]:fo(l,s,"end",Math.min)}})}}return a}(i,s,n);for(const{source:e,target:l,start:h,end:c}of r){const{style:{backgroundColor:r=o}={}}=e,d=!0!==s;t.save(),t.fillStyle=r,ko(t,a,d&&co(n,h,c)),t.beginPath();const u=!!i.pathSegment(t,e);let f;if(d){u?t.closePath():So(t,s,c,n);const e=!!s.pathSegment(t,l,{move:u,reverse:!0});f=u&&e,f||So(t,s,h,n)}t.closePath(),t.fill(f?"evenodd":"nonzero"),t.restore()}}function ko(t,e,i){const{top:s,bottom:n}=e.chart.chartArea,{property:o,start:a,end:r}=i||{};"x"===o&&(t.beginPath(),t.rect(a,s,r-a,n-s),t.clip())}function So(t,e,i,s){const n=e.interpolate(i,s);n&&t.lineTo(n.x,n.y)}var Po={id:"filler",afterDatasetsUpdate(t,e,i){const s=(t.data.datasets||[]).length,n=[];let o,a,r,l;for(a=0;a<s;++a)o=t.getDatasetMeta(a),r=o.dataset,l=null,r&&r.options&&r instanceof Gn&&(l={visible:t.isDatasetVisible(a),index:a,fill:mo(r,a,s),chart:t,axis:o.controller.options.indexAxis,scale:o.vScale,line:r}),o.$filler=l,n.push(l);for(a=0;a<s;++a)l=n[a],l&&!1!==l.fill&&(l.fill=po(n,a,i.propagate))},beforeDraw(t,e,i){const s="beforeDraw"===i.drawTime,n=t.getSortedVisibleDatasetMetas(),o=t.chartArea;for(let e=n.length-1;e>=0;--e){const i=n[e].$filler;i&&(i.line.updateControlPoints(o,i.axis),s&&vo(t.ctx,i,o))}},beforeDatasetsDraw(t,e,i){if("beforeDatasetsDraw"!==i.drawTime)return;const s=t.getSortedVisibleDatasetMetas();for(let e=s.length-1;e>=0;--e){const i=s[e].$filler;i&&vo(t.ctx,i,t.chartArea)}},beforeDatasetDraw(t,e,i){const s=e.meta.$filler;s&&!1!==s.fill&&"beforeDatasetDraw"===i.drawTime&&vo(t.ctx,s,t.chartArea)},defaults:{propagate:!0,drawTime:"beforeDatasetDraw"}};const Do=(t,e)=>{let{boxHeight:i=e,boxWidth:s=e}=t;return t.usePointStyle&&(i=Math.min(i,e),s=Math.min(s,e)),{boxWidth:s,boxHeight:i,itemHeight:Math.max(e,i)}};class Co extends Os{constructor(t){super(),this._added=!1,this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1,this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this.legendItems=void 0,this.columnSizes=void 0,this.lineWidths=void 0,this.maxHeight=void 0,this.maxWidth=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.height=void 0,this.width=void 0,this._margins=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e,i){this.maxWidth=t,this.maxHeight=e,this._margins=i,this.setDimensions(),this.buildLabels(),this.fit()}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=this._margins.left,this.right=this.width):(this.height=this.maxHeight,this.top=this._margins.top,this.bottom=this.height)}buildLabels(){const t=this.options.labels||{};let e=tt(t.generateLabels,[this.chart],this)||[];t.filter&&(e=e.filter((e=>t.filter(e,this.chart.data)))),t.sort&&(e=e.sort(((e,i)=>t.sort(e,i,this.chart.data)))),this.options.reverse&&e.reverse(),this.legendItems=e}fit(){const{options:t,ctx:e}=this;if(!t.display)return void(this.width=this.height=0);const i=t.labels,s=ui(i.font),n=s.size,o=this._computeTitleHeight(),{boxWidth:a,itemHeight:r}=Do(i,n);let l,h;e.font=s.string,this.isHorizontal()?(l=this.maxWidth,h=this._fitRows(o,n,a,r)+10):(h=this.maxHeight,l=this._fitCols(o,n,a,r)+10),this.width=Math.min(l,t.maxWidth||this.maxWidth),this.height=Math.min(h,t.maxHeight||this.maxHeight)}_fitRows(t,e,i,s){const{ctx:n,maxWidth:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.lineWidths=[0],h=s+a;let c=t;n.textAlign="left",n.textBaseline="middle";let d=-1,u=-h;return this.legendItems.forEach(((t,f)=>{const g=i+e/2+n.measureText(t.text).width;(0===f||l[l.length-1]+g+2*a>o)&&(c+=h,l[l.length-(f>0?0:1)]=0,u+=h,d++),r[f]={left:0,top:u,row:d,width:g,height:s},l[l.length-1]+=g+a})),c}_fitCols(t,e,i,s){const{ctx:n,maxHeight:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.columnSizes=[],h=o-t;let c=a,d=0,u=0,f=0,g=0;return this.legendItems.forEach(((t,o)=>{const p=i+e/2+n.measureText(t.text).width;o>0&&u+s+2*a>h&&(c+=d+a,l.push({width:d,height:u}),f+=d+a,g++,d=u=0),r[o]={left:f,top:u,col:g,width:p,height:s},d=Math.max(d,p),u+=s+a})),c+=d,l.push({width:d,height:u}),c}adjustHitBoxes(){if(!this.options.display)return;const t=this._computeTitleHeight(),{legendHitBoxes:e,options:{align:i,labels:{padding:s},rtl:o}}=this,a=mi(o,this.left,this.width);if(this.isHorizontal()){let o=0,r=n(i,this.left+s,this.right-this.lineWidths[o]);for(const l of e)o!==l.row&&(o=l.row,r=n(i,this.left+s,this.right-this.lineWidths[o])),l.top+=this.top+t+s,l.left=a.leftForLtr(a.x(r),l.width),r+=l.width+s}else{let o=0,r=n(i,this.top+t+s,this.bottom-this.columnSizes[o].height);for(const l of e)l.col!==o&&(o=l.col,r=n(i,this.top+t+s,this.bottom-this.columnSizes[o].height)),l.top=r,l.left+=this.left+s,l.left=a.leftForLtr(a.x(l.left),l.width),r+=l.height+s}}isHorizontal(){return"top"===this.options.position||"bottom"===this.options.position}draw(){if(this.options.display){const t=this.ctx;we(t,this),this._draw(),Me(t)}}_draw(){const{options:t,columnSizes:e,lineWidths:i,ctx:s}=this,{align:a,labels:r}=t,l=yt.color,h=mi(t.rtl,this.left,this.width),c=ui(r.font),{color:d,padding:u}=r,f=c.size,g=f/2;let p;this.drawTitle(),s.textAlign=h.textAlign("left"),s.textBaseline="middle",s.lineWidth=.5,s.font=c.string;const{boxWidth:m,boxHeight:b,itemHeight:x}=Do(r,f),_=this.isHorizontal(),y=this._computeTitleHeight();p=_?{x:n(a,this.left+u,this.right-i[0]),y:this.top+u+y,line:0}:{x:this.left+u,y:n(a,this.top+y+u,this.bottom-e[0].height),line:0},bi(this.ctx,t.textDirection);const v=x+u;this.legendItems.forEach(((w,M)=>{s.strokeStyle=w.fontColor||d,s.fillStyle=w.fontColor||d;const k=s.measureText(w.text).width,S=h.textAlign(w.textAlign||(w.textAlign=r.textAlign)),P=m+g+k;let D=p.x,C=p.y;h.setWidth(this.width),_?M>0&&D+P+u>this.right&&(C=p.y+=v,p.line++,D=p.x=n(a,this.left+u,this.right-i[p.line])):M>0&&C+v>this.bottom&&(D=p.x=D+e[p.line].width+u,p.line++,C=p.y=n(a,this.top+y+u,this.bottom-e[p.line].height));!function(t,e,i){if(isNaN(m)||m<=0||isNaN(b)||b<0)return;s.save();const n=Z(i.lineWidth,1);if(s.fillStyle=Z(i.fillStyle,l),s.lineCap=Z(i.lineCap,"butt"),s.lineDashOffset=Z(i.lineDashOffset,0),s.lineJoin=Z(i.lineJoin,"miter"),s.lineWidth=n,s.strokeStyle=Z(i.strokeStyle,l),s.setLineDash(Z(i.lineDash,[])),r.usePointStyle){const o={radius:m*Math.SQRT2/2,pointStyle:i.pointStyle,rotation:i.rotation,borderWidth:n},a=h.xPlus(t,m/2);ye(s,o,a,e+g)}else{const o=e+Math.max((f-b)/2,0),a=h.leftForLtr(t,m),r=ci(i.borderRadius);s.beginPath(),Object.values(r).some((t=>0!==t))?Ce(s,{x:a,y:o,w:m,h:b,radius:r}):s.rect(a,o,m,b),s.fill(),0!==n&&s.stroke()}s.restore()}(h.x(D),C,w),D=o(S,D+m+g,_?D+P:this.right,t.rtl),function(t,e,i){Pe(s,i.text,t,e+x/2,c,{strikethrough:i.hidden,textAlign:h.textAlign(i.textAlign)})}(h.x(D),C,w),_?p.x+=P+u:p.y+=v})),xi(this.ctx,t.textDirection)}drawTitle(){const t=this.options,e=t.title,i=ui(e.font),o=di(e.padding);if(!e.display)return;const a=mi(t.rtl,this.left,this.width),r=this.ctx,l=e.position,h=i.size/2,c=o.top+h;let d,u=this.left,f=this.width;if(this.isHorizontal())f=Math.max(...this.lineWidths),d=this.top+c,u=n(t.align,u,this.right-f);else{const e=this.columnSizes.reduce(((t,e)=>Math.max(t,e.height)),0);d=c+n(t.align,this.top,this.bottom-e-t.labels.padding-this._computeTitleHeight())}const g=n(l,u,u+f);r.textAlign=a.textAlign(s(l)),r.textBaseline="middle",r.strokeStyle=e.color,r.fillStyle=e.color,r.font=i.string,Pe(r,e.text,g,d,i)}_computeTitleHeight(){const t=this.options.title,e=ui(t.font),i=di(t.padding);return t.display?e.lineHeight+i.height:0}_getLegendItemAt(t,e){let i,s,n;if(ee(t,this.left,this.right)&&ee(e,this.top,this.bottom))for(n=this.legendHitBoxes,i=0;i<n.length;++i)if(s=n[i],ee(t,s.left,s.left+s.width)&&ee(e,s.top,s.top+s.height))return this.legendItems[i];return null}handleEvent(t){const e=this.options;if(!function(t,e){if(("mousemove"===t||"mouseout"===t)&&(e.onHover||e.onLeave))return!0;if(e.onClick&&("click"===t||"mouseup"===t))return!0;return!1}(t.type,e))return;const i=this._getLegendItemAt(t.x,t.y);if("mousemove"===t.type||"mouseout"===t.type){const o=this._hoveredItem,a=(n=i,null!==(s=o)&&null!==n&&s.datasetIndex===n.datasetIndex&&s.index===n.index);o&&!a&&tt(e.onLeave,[t,o,this],this),this._hoveredItem=i,i&&!a&&tt(e.onHover,[t,i,this],this)}else i&&tt(e.onClick,[t,i,this],this);var s,n}}var Oo={id:"legend",_element:Co,start(t,e,i){const s=t.legend=new Co({ctx:t.ctx,options:i,chart:t});Xi.configure(t,s,i),Xi.addBox(t,s)},stop(t){Xi.removeBox(t,t.legend),delete t.legend},beforeUpdate(t,e,i){const s=t.legend;Xi.configure(t,s,i),s.options=i},afterUpdate(t){const e=t.legend;e.buildLabels(),e.adjustHitBoxes()},afterEvent(t,e){e.replay||t.legend.handleEvent(e.event)},defaults:{display:!0,position:"top",align:"center",fullSize:!0,reverse:!1,weight:1e3,onClick(t,e,i){const s=e.datasetIndex,n=i.chart;n.isDatasetVisible(s)?(n.hide(s),e.hidden=!0):(n.show(s),e.hidden=!1)},onHover:null,onLeave:null,labels:{color:t=>t.chart.options.color,boxWidth:40,padding:10,generateLabels(t){const e=t.data.datasets,{labels:{usePointStyle:i,pointStyle:s,textAlign:n,color:o}}=t.legend.options;return t._getSortedDatasetMetas().map((t=>{const a=t.controller.getStyle(i?0:void 0),r=di(a.borderWidth);return{text:e[t.index].label,fillStyle:a.backgroundColor,fontColor:o,hidden:!t.visible,lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:(r.width+r.height)/4,strokeStyle:a.borderColor,pointStyle:s||a.pointStyle,rotation:a.rotation,textAlign:n||a.textAlign,borderRadius:0,datasetIndex:t.index}}),this)}},title:{color:t=>t.chart.options.color,display:!1,position:"center",text:""}},descriptors:{_scriptable:t=>!t.startsWith("on"),labels:{_scriptable:t=>!["generateLabels","filter","sort"].includes(t)}}};class Ao extends Os{constructor(t){super(),this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this._padding=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e){const i=this.options;if(this.left=0,this.top=0,!i.display)return void(this.width=this.height=this.right=this.bottom=0);this.width=this.right=t,this.height=this.bottom=e;const s=X(i.text)?i.text.length:1;this._padding=di(i.padding);const n=s*ui(i.font).lineHeight+this._padding.height;this.isHorizontal()?this.height=n:this.width=n}isHorizontal(){const t=this.options.position;return"top"===t||"bottom"===t}_drawArgs(t){const{top:e,left:i,bottom:s,right:o,options:a}=this,r=a.align;let l,h,c,d=0;return this.isHorizontal()?(h=n(r,i,o),c=e+t,l=o-i):("left"===a.position?(h=i+t,c=n(r,s,e),d=-.5*Ot):(h=o-t,c=n(r,e,s),d=.5*Ot),l=s-e),{titleX:h,titleY:c,maxWidth:l,rotation:d}}draw(){const t=this.ctx,e=this.options;if(!e.display)return;const i=ui(e.font),n=i.lineHeight/2+this._padding.top,{titleX:o,titleY:a,maxWidth:r,rotation:l}=this._drawArgs(n);Pe(t,e.text,0,0,i,{color:e.color,maxWidth:r,rotation:l,textAlign:s(e.align),textBaseline:"middle",translation:[o,a]})}}var To={id:"title",_element:Ao,start(t,e,i){!function(t,e){const i=new Ao({ctx:t.ctx,options:e,chart:t});Xi.configure(t,i,e),Xi.addBox(t,i),t.titleBlock=i}(t,i)},stop(t){const e=t.titleBlock;Xi.removeBox(t,e),delete t.titleBlock},beforeUpdate(t,e,i){const s=t.titleBlock;Xi.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"bold"},fullSize:!0,padding:10,position:"top",text:"",weight:2e3},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Lo=new WeakMap;var Ro={id:"subtitle",start(t,e,i){const s=new Ao({ctx:t.ctx,options:i,chart:t});Xi.configure(t,s,i),Xi.addBox(t,s),Lo.set(t,s)},stop(t){Xi.removeBox(t,Lo.get(t)),Lo.delete(t)},beforeUpdate(t,e,i){const s=Lo.get(t);Xi.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"normal"},fullSize:!0,padding:0,position:"top",text:"",weight:1500},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Eo={average(t){if(!t.length)return!1;let e,i,s=0,n=0,o=0;for(e=0,i=t.length;e<i;++e){const i=t[e].element;if(i&&i.hasValue()){const t=i.tooltipPosition();s+=t.x,n+=t.y,++o}}return{x:s/o,y:n/o}},nearest(t,e){if(!t.length)return!1;let i,s,n,o=e.x,a=e.y,r=Number.POSITIVE_INFINITY;for(i=0,s=t.length;i<s;++i){const s=t[i].element;if(s&&s.hasValue()){const t=Kt(e,s.getCenterPoint());t<r&&(r=t,n=s)}}if(n){const t=n.tooltipPosition();o=t.x,a=t.y}return{x:o,y:a}}};function Io(t,e){return e&&(X(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function zo(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function Fo(t,e){const{element:i,datasetIndex:s,index:n}=e,o=t.getDatasetMeta(s).controller,{label:a,value:r}=o.getLabelAndValue(n);return{chart:t,label:a,parsed:o.getParsed(n),raw:t.data.datasets[s].data[n],formattedValue:r,dataset:o.getDataset(),dataIndex:n,datasetIndex:s,element:i}}function Bo(t,e){const i=t.chart.ctx,{body:s,footer:n,title:o}=t,{boxWidth:a,boxHeight:r}=e,l=ui(e.bodyFont),h=ui(e.titleFont),c=ui(e.footerFont),d=o.length,u=n.length,f=s.length,g=di(e.padding);let p=g.height,m=0,b=s.reduce(((t,e)=>t+e.before.length+e.lines.length+e.after.length),0);if(b+=t.beforeBody.length+t.afterBody.length,d&&(p+=d*h.lineHeight+(d-1)*e.titleSpacing+e.titleMarginBottom),b){p+=f*(e.displayColors?Math.max(r,l.lineHeight):l.lineHeight)+(b-f)*l.lineHeight+(b-1)*e.bodySpacing}u&&(p+=e.footerMarginTop+u*c.lineHeight+(u-1)*e.footerSpacing);let x=0;const _=function(t){m=Math.max(m,i.measureText(t).width+x)};return i.save(),i.font=h.string,et(t.title,_),i.font=l.string,et(t.beforeBody.concat(t.afterBody),_),x=e.displayColors?a+2+e.boxPadding:0,et(s,(t=>{et(t.before,_),et(t.lines,_),et(t.after,_)})),x=0,i.font=c.string,et(t.footer,_),i.restore(),m+=g.width,{width:m,height:p}}function Vo(t,e,i,s){const{x:n,width:o}=i,{width:a,chartArea:{left:r,right:l}}=t;let h="center";return"center"===s?h=n<=(r+l)/2?"left":"right":n<=o/2?h="left":n>=a-o/2&&(h="right"),function(t,e,i,s){const{x:n,width:o}=s,a=i.caretSize+i.caretPadding;return"left"===t&&n+o+a>e.width||"right"===t&&n-o-a<0||void 0}(h,t,e,i)&&(h="center"),h}function No(t,e,i){const s=i.yAlign||e.yAlign||function(t,e){const{y:i,height:s}=e;return i<s/2?"top":i>t.height-s/2?"bottom":"center"}(t,i);return{xAlign:i.xAlign||e.xAlign||Vo(t,e,i,s),yAlign:s}}function Wo(t,e,i,s){const{caretSize:n,caretPadding:o,cornerRadius:a}=t,{xAlign:r,yAlign:l}=i,h=n+o,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=ci(a);let g=function(t,e){let{x:i,width:s}=t;return"right"===e?i-=s:"center"===e&&(i-=s/2),i}(e,r);const p=function(t,e,i){let{y:s,height:n}=t;return"top"===e?s+=i:s-="bottom"===e?n+i:n/2,s}(e,l,h);return"center"===l?"left"===r?g+=h:"right"===r&&(g-=h):"left"===r?g-=Math.max(c,u)+n:"right"===r&&(g+=Math.max(d,f)+n),{x:Qt(g,0,s.width-e.width),y:Qt(p,0,s.height-e.height)}}function Ho(t,e,i){const s=di(i.padding);return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-s.right:t.x+s.left}function jo(t){return Io([],zo(t))}function $o(t,e){const i=e&&e.dataset&&e.dataset.tooltip&&e.dataset.tooltip.callbacks;return i?t.override(i):t}class Yo extends Os{constructor(t){super(),this.opacity=0,this._active=[],this._eventPosition=void 0,this._size=void 0,this._cachedAnimations=void 0,this._tooltipItems=[],this.$animations=void 0,this.$context=void 0,this.chart=t.chart||t._chart,this._chart=this.chart,this.options=t.options,this.dataPoints=void 0,this.title=void 0,this.beforeBody=void 0,this.body=void 0,this.afterBody=void 0,this.footer=void 0,this.xAlign=void 0,this.yAlign=void 0,this.x=void 0,this.y=void 0,this.height=void 0,this.width=void 0,this.caretX=void 0,this.caretY=void 0,this.labelColors=void 0,this.labelPointStyles=void 0,this.labelTextColors=void 0}initialize(t){this.options=t,this._cachedAnimations=void 0,this.$context=void 0}_resolveAnimations(){const t=this._cachedAnimations;if(t)return t;const e=this.chart,i=this.options.setContext(this.getContext()),s=i.enabled&&e.options.animation&&i.animations,n=new ms(this.chart,s);return s._cacheable&&(this._cachedAnimations=Object.freeze(n)),n}getContext(){return this.$context||(this.$context=(t=this.chart.getContext(),e=this,i=this._tooltipItems,pi(t,{tooltip:e,tooltipItems:i,type:"tooltip"})));var t,e,i}getTitle(t,e){const{callbacks:i}=e,s=i.beforeTitle.apply(this,[t]),n=i.title.apply(this,[t]),o=i.afterTitle.apply(this,[t]);let a=[];return a=Io(a,zo(s)),a=Io(a,zo(n)),a=Io(a,zo(o)),a}getBeforeBody(t,e){return jo(e.callbacks.beforeBody.apply(this,[t]))}getBody(t,e){const{callbacks:i}=e,s=[];return et(t,(t=>{const e={before:[],lines:[],after:[]},n=$o(i,t);Io(e.before,zo(n.beforeLabel.call(this,t))),Io(e.lines,n.label.call(this,t)),Io(e.after,zo(n.afterLabel.call(this,t))),s.push(e)})),s}getAfterBody(t,e){return jo(e.callbacks.afterBody.apply(this,[t]))}getFooter(t,e){const{callbacks:i}=e,s=i.beforeFooter.apply(this,[t]),n=i.footer.apply(this,[t]),o=i.afterFooter.apply(this,[t]);let a=[];return a=Io(a,zo(s)),a=Io(a,zo(n)),a=Io(a,zo(o)),a}_createItems(t){const e=this._active,i=this.chart.data,s=[],n=[],o=[];let a,r,l=[];for(a=0,r=e.length;a<r;++a)l.push(Fo(this.chart,e[a]));return t.filter&&(l=l.filter(((e,s,n)=>t.filter(e,s,n,i)))),t.itemSort&&(l=l.sort(((e,s)=>t.itemSort(e,s,i)))),et(l,(e=>{const i=$o(t.callbacks,e);s.push(i.labelColor.call(this,e)),n.push(i.labelPointStyle.call(this,e)),o.push(i.labelTextColor.call(this,e))})),this.labelColors=s,this.labelPointStyles=n,this.labelTextColors=o,this.dataPoints=l,l}update(t,e){const i=this.options.setContext(this.getContext()),s=this._active;let n,o=[];if(s.length){const t=Eo[i.position].call(this,s,this._eventPosition);o=this._createItems(i),this.title=this.getTitle(o,i),this.beforeBody=this.getBeforeBody(o,i),this.body=this.getBody(o,i),this.afterBody=this.getAfterBody(o,i),this.footer=this.getFooter(o,i);const e=this._size=Bo(this,i),a=Object.assign({},t,e),r=No(this.chart,i,a),l=Wo(i,a,r,this.chart);this.xAlign=r.xAlign,this.yAlign=r.yAlign,n={opacity:1,x:l.x,y:l.y,width:e.width,height:e.height,caretX:t.x,caretY:t.y}}else 0!==this.opacity&&(n={opacity:0});this._tooltipItems=o,this.$context=void 0,n&&this._resolveAnimations().update(this,n),t&&i.external&&i.external.call(this,{chart:this.chart,tooltip:this,replay:e})}drawCaret(t,e,i,s){const n=this.getCaretPosition(t,i,s);e.lineTo(n.x1,n.y1),e.lineTo(n.x2,n.y2),e.lineTo(n.x3,n.y3)}getCaretPosition(t,e,i){const{xAlign:s,yAlign:n}=this,{caretSize:o,cornerRadius:a}=i,{topLeft:r,topRight:l,bottomLeft:h,bottomRight:c}=ci(a),{x:d,y:u}=t,{width:f,height:g}=e;let p,m,b,x,_,y;return"center"===n?(_=u+g/2,"left"===s?(p=d,m=p-o,x=_+o,y=_-o):(p=d+f,m=p+o,x=_-o,y=_+o),b=p):(m="left"===s?d+Math.max(r,h)+o:"right"===s?d+f-Math.max(l,c)-o:this.caretX,"top"===n?(x=u,_=x-o,p=m-o,b=m+o):(x=u+g,_=x+o,p=m+o,b=m-o),y=x),{x1:p,x2:m,x3:b,y1:x,y2:_,y3:y}}drawTitle(t,e,i){const s=this.title,n=s.length;let o,a,r;if(n){const l=mi(i.rtl,this.x,this.width);for(t.x=Ho(this,i.titleAlign,i),e.textAlign=l.textAlign(i.titleAlign),e.textBaseline="middle",o=ui(i.titleFont),a=i.titleSpacing,e.fillStyle=i.titleColor,e.font=o.string,r=0;r<n;++r)e.fillText(s[r],l.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+a,r+1===n&&(t.y+=i.titleMarginBottom-a)}}_drawColorBox(t,e,i,s,n){const o=this.labelColors[i],a=this.labelPointStyles[i],{boxHeight:r,boxWidth:l,boxPadding:h}=n,c=ui(n.bodyFont),d=Ho(this,"left",n),u=s.x(d),f=r<c.lineHeight?(c.lineHeight-r)/2:0,g=e.y+f;if(n.usePointStyle){const e={radius:Math.min(l,r)/2,pointStyle:a.pointStyle,rotation:a.rotation,borderWidth:1},i=s.leftForLtr(u,l)+l/2,h=g+r/2;t.strokeStyle=n.multiKeyBackground,t.fillStyle=n.multiKeyBackground,ye(t,e,i,h),t.strokeStyle=o.borderColor,t.fillStyle=o.backgroundColor,ye(t,e,i,h)}else{t.lineWidth=o.borderWidth||1,t.strokeStyle=o.borderColor,t.setLineDash(o.borderDash||[]),t.lineDashOffset=o.borderDashOffset||0;const e=s.leftForLtr(u,l-h),i=s.leftForLtr(s.xPlus(u,1),l-h-2),a=ci(o.borderRadius);Object.values(a).some((t=>0!==t))?(t.beginPath(),t.fillStyle=n.multiKeyBackground,Ce(t,{x:e,y:g,w:l,h:r,radius:a}),t.fill(),t.stroke(),t.fillStyle=o.backgroundColor,t.beginPath(),Ce(t,{x:i,y:g+1,w:l-2,h:r-2,radius:a}),t.fill()):(t.fillStyle=n.multiKeyBackground,t.fillRect(e,g,l,r),t.strokeRect(e,g,l,r),t.fillStyle=o.backgroundColor,t.fillRect(i,g+1,l-2,r-2))}t.fillStyle=this.labelTextColors[i]}drawBody(t,e,i){const{body:s}=this,{bodySpacing:n,bodyAlign:o,displayColors:a,boxHeight:r,boxWidth:l,boxPadding:h}=i,c=ui(i.bodyFont);let d=c.lineHeight,u=0;const f=mi(i.rtl,this.x,this.width),g=function(i){e.fillText(i,f.x(t.x+u),t.y+d/2),t.y+=d+n},p=f.textAlign(o);let m,b,x,_,y,v,w;for(e.textAlign=o,e.textBaseline="middle",e.font=c.string,t.x=Ho(this,p,i),e.fillStyle=i.bodyColor,et(this.beforeBody,g),u=a&&"right"!==p?"center"===o?l/2+h:l+2+h:0,_=0,v=s.length;_<v;++_){for(m=s[_],b=this.labelTextColors[_],e.fillStyle=b,et(m.before,g),x=m.lines,a&&x.length&&(this._drawColorBox(e,t,_,f,i),d=Math.max(c.lineHeight,r)),y=0,w=x.length;y<w;++y)g(x[y]),d=c.lineHeight;et(m.after,g)}u=0,d=c.lineHeight,et(this.afterBody,g),t.y-=n}drawFooter(t,e,i){const s=this.footer,n=s.length;let o,a;if(n){const r=mi(i.rtl,this.x,this.width);for(t.x=Ho(this,i.footerAlign,i),t.y+=i.footerMarginTop,e.textAlign=r.textAlign(i.footerAlign),e.textBaseline="middle",o=ui(i.footerFont),e.fillStyle=i.footerColor,e.font=o.string,a=0;a<n;++a)e.fillText(s[a],r.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+i.footerSpacing}}drawBackground(t,e,i,s){const{xAlign:n,yAlign:o}=this,{x:a,y:r}=t,{width:l,height:h}=i,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=ci(s.cornerRadius);e.fillStyle=s.backgroundColor,e.strokeStyle=s.borderColor,e.lineWidth=s.borderWidth,e.beginPath(),e.moveTo(a+c,r),"top"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+l-d,r),e.quadraticCurveTo(a+l,r,a+l,r+d),"center"===o&&"right"===n&&this.drawCaret(t,e,i,s),e.lineTo(a+l,r+h-f),e.quadraticCurveTo(a+l,r+h,a+l-f,r+h),"bottom"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+u,r+h),e.quadraticCurveTo(a,r+h,a,r+h-u),"center"===o&&"left"===n&&this.drawCaret(t,e,i,s),e.lineTo(a,r+c),e.quadraticCurveTo(a,r,a+c,r),e.closePath(),e.fill(),s.borderWidth>0&&e.stroke()}_updateAnimationTarget(t){const e=this.chart,i=this.$animations,s=i&&i.x,n=i&&i.y;if(s||n){const i=Eo[t.position].call(this,this._active,this._eventPosition);if(!i)return;const o=this._size=Bo(this,t),a=Object.assign({},i,this._size),r=No(e,t,a),l=Wo(t,a,r,e);s._to===l.x&&n._to===l.y||(this.xAlign=r.xAlign,this.yAlign=r.yAlign,this.width=o.width,this.height=o.height,this.caretX=i.x,this.caretY=i.y,this._resolveAnimations().update(this,l))}}_willRender(){return!!this.opacity}draw(t){const e=this.options.setContext(this.getContext());let i=this.opacity;if(!i)return;this._updateAnimationTarget(e);const s={width:this.width,height:this.height},n={x:this.x,y:this.y};i=Math.abs(i)<.001?0:i;const o=di(e.padding),a=this.title.length||this.beforeBody.length||this.body.length||this.afterBody.length||this.footer.length;e.enabled&&a&&(t.save(),t.globalAlpha=i,this.drawBackground(n,t,s,e),bi(t,e.textDirection),n.y+=o.top,this.drawTitle(n,t,e),this.drawBody(n,t,e),this.drawFooter(n,t,e),xi(t,e.textDirection),t.restore())}getActiveElements(){return this._active||[]}setActiveElements(t,e){const i=this._active,s=t.map((({datasetIndex:t,index:e})=>{const i=this.chart.getDatasetMeta(t);if(!i)throw new Error("Cannot find a dataset at index "+t);return{datasetIndex:t,element:i.data[e],index:e}})),n=!it(i,s),o=this._positionChanged(s,e);(n||o)&&(this._active=s,this._eventPosition=e,this._ignoreReplayEvents=!0,this.update(!0))}handleEvent(t,e,i=!0){if(e&&this._ignoreReplayEvents)return!1;this._ignoreReplayEvents=!1;const s=this.options,n=this._active||[],o=this._getActiveElements(t,n,e,i),a=this._positionChanged(o,t),r=e||!it(o,n)||a;return r&&(this._active=o,(s.enabled||s.external)&&(this._eventPosition={x:t.x,y:t.y},this.update(!0,e))),r}_getActiveElements(t,e,i,s){const n=this.options;if("mouseout"===t.type)return[];if(!s)return e;const o=this.chart.getElementsAtEventForMode(t,n.mode,n,i);return n.reverse&&o.reverse(),o}_positionChanged(t,e){const{caretX:i,caretY:s,options:n}=this,o=Eo[n.position].call(this,t,e);return!1!==o&&(i!==o.x||s!==o.y)}}Yo.positioners=Eo;var Uo={id:"tooltip",_element:Yo,positioners:Eo,afterInit(t,e,i){i&&(t.tooltip=new Yo({chart:t,options:i}))},beforeUpdate(t,e,i){t.tooltip&&t.tooltip.initialize(i)},reset(t,e,i){t.tooltip&&t.tooltip.initialize(i)},afterDraw(t){const e=t.tooltip;if(e&&e._willRender()){const i={tooltip:e};if(!1===t.notifyPlugins("beforeTooltipDraw",i))return;e.draw(t.ctx),t.notifyPlugins("afterTooltipDraw",i)}},afterEvent(t,e){if(t.tooltip){const i=e.replay;t.tooltip.handleEvent(e.event,i,e.inChartArea)&&(e.changed=!0)}},defaults:{enabled:!0,external:null,position:"average",backgroundColor:"rgba(0,0,0,0.8)",titleColor:"#fff",titleFont:{weight:"bold"},titleSpacing:2,titleMarginBottom:6,titleAlign:"left",bodyColor:"#fff",bodySpacing:2,bodyFont:{},bodyAlign:"left",footerColor:"#fff",footerSpacing:2,footerMarginTop:6,footerFont:{weight:"bold"},footerAlign:"left",padding:6,caretPadding:2,caretSize:5,cornerRadius:6,boxHeight:(t,e)=>e.bodyFont.size,boxWidth:(t,e)=>e.bodyFont.size,multiKeyBackground:"#fff",displayColors:!0,boxPadding:0,borderColor:"rgba(0,0,0,0)",borderWidth:0,animation:{duration:400,easing:"easeOutQuart"},animations:{numbers:{type:"number",properties:["x","y","width","height","caretX","caretY"]},opacity:{easing:"linear",duration:200}},callbacks:{beforeTitle:$,title(t){if(t.length>0){const e=t[0],i=e.chart.data.labels,s=i?i.length:0;if(this&&this.options&&"dataset"===this.options.mode)return e.dataset.label||"";if(e.label)return e.label;if(s>0&&e.dataIndex<s)return i[e.dataIndex]}return""},afterTitle:$,beforeBody:$,beforeLabel:$,label(t){if(this&&this.options&&"dataset"===this.options.mode)return t.label+": "+t.formattedValue||t.formattedValue;let e=t.dataset.label||"";e&&(e+=": ");const i=t.formattedValue;return U(i)||(e+=i),e},labelColor(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{borderColor:e.borderColor,backgroundColor:e.backgroundColor,borderWidth:e.borderWidth,borderDash:e.borderDash,borderDashOffset:e.borderDashOffset,borderRadius:0}},labelTextColor(){return this.options.bodyColor},labelPointStyle(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{pointStyle:e.pointStyle,rotation:e.rotation}},afterLabel:$,afterBody:$,beforeFooter:$,footer:$,afterFooter:$}},defaultRoutes:{bodyFont:"font",footerFont:"font",titleFont:"font"},descriptors:{_scriptable:t=>"filter"!==t&&"itemSort"!==t&&"external"!==t,_indexable:!1,callbacks:{_scriptable:!1,_indexable:!1},animation:{_fallback:!1},animations:{_fallback:"animation"}},additionalOptionScopes:["interaction"]},Xo=Object.freeze({__proto__:null,Decimation:ho,Filler:Po,Legend:Oo,SubTitle:Ro,Title:To,Tooltip:Uo});function qo(t,e,i,s){const n=t.indexOf(e);if(-1===n)return((t,e,i,s)=>("string"==typeof e?(i=t.push(e)-1,s.unshift({index:i,label:e})):isNaN(e)&&(i=null),i))(t,e,i,s);return n!==t.lastIndexOf(e)?i:n}class Ko extends Ns{constructor(t){super(t),this._startValue=void 0,this._valueRange=0,this._addedLabels=[]}init(t){const e=this._addedLabels;if(e.length){const t=this.getLabels();for(const{index:i,label:s}of e)t[i]===s&&t.splice(i,1);this._addedLabels=[]}super.init(t)}parse(t,e){if(U(t))return null;const i=this.getLabels();return((t,e)=>null===t?null:Qt(Math.round(t),0,e))(e=isFinite(e)&&i[e]===t?e:qo(i,t,Z(e,t),this._addedLabels),i.length-1)}determineDataLimits(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let{min:i,max:s}=this.getMinMax(!0);"ticks"===this.options.bounds&&(t||(i=0),e||(s=this.getLabels().length-1)),this.min=i,this.max=s}buildTicks(){const t=this.min,e=this.max,i=this.options.offset,s=[];let n=this.getLabels();n=0===t&&e===n.length-1?n:n.slice(t,e+1),this._valueRange=Math.max(n.length-(i?0:1),1),this._startValue=this.min-(i?.5:0);for(let i=t;i<=e;i++)s.push({value:i});return s}getLabelForValue(t){const e=this.getLabels();return t>=0&&t<e.length?e[t]:t}configure(){super.configure(),this.isHorizontal()||(this._reversePixels=!this._reversePixels)}getPixelForValue(t){return"number"!=typeof t&&(t=this.parse(t)),null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getValueForPixel(t){return Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange)}getBasePixel(){return this.bottom}}function Go(t,e,{horizontal:i,minRotation:s}){const n=Yt(s),o=(i?Math.sin(n):Math.cos(n))||.001,a=.75*e*(""+t).length;return Math.min(e/o,a)}Ko.id="category",Ko.defaults={ticks:{callback:Ko.prototype.getLabelForValue}};class Zo extends Ns{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._endValue=void 0,this._valueRange=0}parse(t,e){return U(t)||("number"==typeof t||t instanceof Number)&&!isFinite(+t)?null:+t}handleTickRangeOptions(){const{beginAtZero:t}=this.options,{minDefined:e,maxDefined:i}=this.getUserBounds();let{min:s,max:n}=this;const o=t=>s=e?s:t,a=t=>n=i?n:t;if(t){const t=Bt(s),e=Bt(n);t<0&&e<0?a(0):t>0&&e>0&&o(0)}if(s===n){let e=1;(n>=Number.MAX_SAFE_INTEGER||s<=Number.MIN_SAFE_INTEGER)&&(e=Math.abs(.05*n)),a(n+e),t||o(s-e)}this.min=s,this.max=n}getTickLimit(){const t=this.options.ticks;let e,{maxTicksLimit:i,stepSize:s}=t;return s?(e=Math.ceil(this.max/s)-Math.floor(this.min/s)+1,e>1e3&&(console.warn(`scales.${this.id}.ticks.stepSize: ${s} would result generating up to ${e} ticks. Limiting to 1000.`),e=1e3)):(e=this.computeTickLimit(),i=i||11),i&&(e=Math.min(i,e)),e}computeTickLimit(){return Number.POSITIVE_INFINITY}buildTicks(){const t=this.options,e=t.ticks;let i=this.getTickLimit();i=Math.max(2,i);const s=function(t,e){const i=[],{bounds:s,step:n,min:o,max:a,precision:r,count:l,maxTicks:h,maxDigits:c,includeBounds:d}=t,u=n||1,f=h-1,{min:g,max:p}=e,m=!U(o),b=!U(a),x=!U(l),_=(p-g)/(c+1);let y,v,w,M,k=Vt((p-g)/f/u)*u;if(k<1e-14&&!m&&!b)return[{value:g},{value:p}];M=Math.ceil(p/k)-Math.floor(g/k),M>f&&(k=Vt(M*k/f/u)*u),U(r)||(y=Math.pow(10,r),k=Math.ceil(k*y)/y),"ticks"===s?(v=Math.floor(g/k)*k,w=Math.ceil(p/k)*k):(v=g,w=p),m&&b&&n&&jt((a-o)/n,k/1e3)?(M=Math.round(Math.min((a-o)/k,h)),k=(a-o)/M,v=o,w=a):x?(v=m?o:v,w=b?a:w,M=l-1,k=(w-v)/M):(M=(w-v)/k,M=Ht(M,Math.round(M),k/1e3)?Math.round(M):Math.ceil(M));const S=Math.max(Xt(k),Xt(v));y=Math.pow(10,U(r)?S:r),v=Math.round(v*y)/y,w=Math.round(w*y)/y;let P=0;for(m&&(d&&v!==o?(i.push({value:o}),v<o&&P++,Ht(Math.round((v+P*k)*y)/y,o,Go(o,_,t))&&P++):v<o&&P++);P<M;++P)i.push({value:Math.round((v+P*k)*y)/y});return b&&d&&w!==a?i.length&&Ht(i[i.length-1].value,a,Go(a,_,t))?i[i.length-1].value=a:i.push({value:a}):b&&w!==a||i.push({value:w}),i}({maxTicks:i,bounds:t.bounds,min:t.min,max:t.max,precision:e.precision,step:e.stepSize,count:e.count,maxDigits:this._maxDigits(),horizontal:this.isHorizontal(),minRotation:e.minRotation||0,includeBounds:!1!==e.includeBounds},this._range||this);return"ticks"===t.bounds&&$t(s,this,"value"),t.reverse?(s.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),s}configure(){const t=this.ticks;let e=this.min,i=this.max;if(super.configure(),this.options.offset&&t.length){const s=(i-e)/Math.max(t.length-1,1)/2;e-=s,i+=s}this._startValue=e,this._endValue=i,this._valueRange=i-e}getLabelForValue(t){return ni(t,this.chart.options.locale,this.options.ticks.format)}}class Jo extends Zo{determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=K(t)?t:0,this.max=K(e)?e:1,this.handleTickRangeOptions()}computeTickLimit(){const t=this.isHorizontal(),e=t?this.width:this.height,i=Yt(this.options.ticks.minRotation),s=(t?Math.sin(i):Math.cos(i))||.001,n=this._resolveTickFontOptions(0);return Math.ceil(e/Math.min(40,n.lineHeight/s))}getPixelForValue(t){return null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getValueForPixel(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange}}function Qo(t){return 1===t/Math.pow(10,Math.floor(Ft(t)))}Jo.id="linear",Jo.defaults={ticks:{callback:Ts.formatters.numeric}};class ta extends Ns{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._valueRange=0}parse(t,e){const i=Zo.prototype.parse.apply(this,[t,e]);if(0!==i)return K(i)&&i>0?i:null;this._zero=!0}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=K(t)?Math.max(0,t):null,this.max=K(e)?Math.max(0,e):null,this.options.beginAtZero&&(this._zero=!0),this.handleTickRangeOptions()}handleTickRangeOptions(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let i=this.min,s=this.max;const n=e=>i=t?i:e,o=t=>s=e?s:t,a=(t,e)=>Math.pow(10,Math.floor(Ft(t))+e);i===s&&(i<=0?(n(1),o(10)):(n(a(i,-1)),o(a(s,1)))),i<=0&&n(a(s,-1)),s<=0&&o(a(i,1)),this._zero&&this.min!==this._suggestedMin&&i===a(this.min,0)&&n(a(i,-1)),this.min=i,this.max=s}buildTicks(){const t=this.options,e=function(t,e){const i=Math.floor(Ft(e.max)),s=Math.ceil(e.max/Math.pow(10,i)),n=[];let o=G(t.min,Math.pow(10,Math.floor(Ft(e.min)))),a=Math.floor(Ft(o)),r=Math.floor(o/Math.pow(10,a)),l=a<0?Math.pow(10,Math.abs(a)):1;do{n.push({value:o,major:Qo(o)}),++r,10===r&&(r=1,++a,l=a>=0?1:l),o=Math.round(r*Math.pow(10,a)*l)/l}while(a<i||a===i&&r<s);const h=G(t.max,o);return n.push({value:h,major:Qo(o)}),n}({min:this._userMin,max:this._userMax},this);return"ticks"===t.bounds&&$t(e,this,"value"),t.reverse?(e.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),e}getLabelForValue(t){return void 0===t?"0":ni(t,this.chart.options.locale,this.options.ticks.format)}configure(){const t=this.min;super.configure(),this._startValue=Ft(t),this._valueRange=Ft(this.max)-Ft(t)}getPixelForValue(t){return void 0!==t&&0!==t||(t=this.min),null===t||isNaN(t)?NaN:this.getPixelForDecimal(t===this.min?0:(Ft(t)-this._startValue)/this._valueRange)}getValueForPixel(t){const e=this.getDecimalForPixel(t);return Math.pow(10,this._startValue+e*this._valueRange)}}function ea(t){const e=t.ticks;if(e.display&&t.display){const t=di(e.backdropPadding);return Z(e.font&&e.font.size,yt.font.size)+t.height}return 0}function ia(t,e,i,s,n){return t===s||t===n?{start:e-i/2,end:e+i/2}:t<s||t>n?{start:e-i,end:e}:{start:e,end:e+i}}function sa(t){const e={l:t.left+t._padding.left,r:t.right-t._padding.right,t:t.top+t._padding.top,b:t.bottom-t._padding.bottom},i=Object.assign({},e),s=[],n=[],o=t._pointLabels.length,a=t.options.pointLabels,r=a.centerPointLabels?Ot/o:0;for(let d=0;d<o;d++){const o=a.setContext(t.getPointLabelContext(d));n[d]=o.padding;const u=t.getPointPosition(d,t.drawingArea+n[d],r),f=ui(o.font),g=(l=t.ctx,h=f,c=X(c=t._pointLabels[d])?c:[c],{w:be(l,h.string,c),h:c.length*h.lineHeight});s[d]=g;const p=Zt(t.getIndexAngle(d)+r),m=Math.round(Ut(p));na(i,e,p,ia(m,u.x,g.w,0,180),ia(m,u.y,g.h,90,270))}var l,h,c;t.setCenterPoint(e.l-i.l,i.r-e.r,e.t-i.t,i.b-e.b),t._pointLabelItems=function(t,e,i){const s=[],n=t._pointLabels.length,o=t.options,a=ea(o)/2,r=t.drawingArea,l=o.pointLabels.centerPointLabels?Ot/n:0;for(let o=0;o<n;o++){const n=t.getPointPosition(o,r+a+i[o],l),h=Math.round(Ut(Zt(n.angle+Et))),c=e[o],d=ra(n.y,c.h,h),u=oa(h),f=aa(n.x,c.w,u);s.push({x:n.x,y:d,textAlign:u,left:f,top:d,right:f+c.w,bottom:d+c.h})}return s}(t,s,n)}function na(t,e,i,s,n){const o=Math.abs(Math.sin(i)),a=Math.abs(Math.cos(i));let r=0,l=0;s.start<e.l?(r=(e.l-s.start)/o,t.l=Math.min(t.l,e.l-r)):s.end>e.r&&(r=(s.end-e.r)/o,t.r=Math.max(t.r,e.r+r)),n.start<e.t?(l=(e.t-n.start)/a,t.t=Math.min(t.t,e.t-l)):n.end>e.b&&(l=(n.end-e.b)/a,t.b=Math.max(t.b,e.b+l))}function oa(t){return 0===t||180===t?"center":t<180?"left":"right"}function aa(t,e,i){return"right"===i?t-=e:"center"===i&&(t-=e/2),t}function ra(t,e,i){return 90===i||270===i?t-=e/2:(i>270||i<90)&&(t-=e),t}function la(t,e,i,s){const{ctx:n}=t;if(i)n.arc(t.xCenter,t.yCenter,e,0,At);else{let i=t.getPointPosition(0,e);n.moveTo(i.x,i.y);for(let o=1;o<s;o++)i=t.getPointPosition(o,e),n.lineTo(i.x,i.y)}}ta.id="logarithmic",ta.defaults={ticks:{callback:Ts.formatters.logarithmic,major:{enabled:!0}}};class ha extends Zo{constructor(t){super(t),this.xCenter=void 0,this.yCenter=void 0,this.drawingArea=void 0,this._pointLabels=[],this._pointLabelItems=[]}setDimensions(){const t=this._padding=di(ea(this.options)/2),e=this.width=this.maxWidth-t.width,i=this.height=this.maxHeight-t.height;this.xCenter=Math.floor(this.left+e/2+t.left),this.yCenter=Math.floor(this.top+i/2+t.top),this.drawingArea=Math.floor(Math.min(e,i)/2)}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!1);this.min=K(t)&&!isNaN(t)?t:0,this.max=K(e)&&!isNaN(e)?e:0,this.handleTickRangeOptions()}computeTickLimit(){return Math.ceil(this.drawingArea/ea(this.options))}generateTickLabels(t){Zo.prototype.generateTickLabels.call(this,t),this._pointLabels=this.getLabels().map(((t,e)=>{const i=tt(this.options.pointLabels.callback,[t,e],this);return i||0===i?i:""})).filter(((t,e)=>this.chart.getDataVisibility(e)))}fit(){const t=this.options;t.display&&t.pointLabels.display?sa(this):this.setCenterPoint(0,0,0,0)}setCenterPoint(t,e,i,s){this.xCenter+=Math.floor((t-e)/2),this.yCenter+=Math.floor((i-s)/2),this.drawingArea-=Math.min(this.drawingArea/2,Math.max(t,e,i,s))}getIndexAngle(t){return Zt(t*(At/(this._pointLabels.length||1))+Yt(this.options.startAngle||0))}getDistanceFromCenterForValue(t){if(U(t))return NaN;const e=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*e:(t-this.min)*e}getValueForDistanceFromCenter(t){if(U(t))return NaN;const e=t/(this.drawingArea/(this.max-this.min));return this.options.reverse?this.max-e:this.min+e}getPointLabelContext(t){const e=this._pointLabels||[];if(t>=0&&t<e.length){const i=e[t];return function(t,e,i){return pi(t,{label:i,index:e,type:"pointLabel"})}(this.getContext(),t,i)}}getPointPosition(t,e,i=0){const s=this.getIndexAngle(t)-Et+i;return{x:Math.cos(s)*e+this.xCenter,y:Math.sin(s)*e+this.yCenter,angle:s}}getPointPositionForValue(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))}getBasePosition(t){return this.getPointPositionForValue(t||0,this.getBaseValue())}getPointLabelPosition(t){const{left:e,top:i,right:s,bottom:n}=this._pointLabelItems[t];return{left:e,top:i,right:s,bottom:n}}drawBackground(){const{backgroundColor:t,grid:{circular:e}}=this.options;if(t){const i=this.ctx;i.save(),i.beginPath(),la(this,this.getDistanceFromCenterForValue(this._endValue),e,this._pointLabels.length),i.closePath(),i.fillStyle=t,i.fill(),i.restore()}}drawGrid(){const t=this.ctx,e=this.options,{angleLines:i,grid:s}=e,n=this._pointLabels.length;let o,a,r;if(e.pointLabels.display&&function(t,e){const{ctx:i,options:{pointLabels:s}}=t;for(let n=e-1;n>=0;n--){const e=s.setContext(t.getPointLabelContext(n)),o=ui(e.font),{x:a,y:r,textAlign:l,left:h,top:c,right:d,bottom:u}=t._pointLabelItems[n],{backdropColor:f}=e;if(!U(f)){const t=ci(e.borderRadius),s=di(e.backdropPadding);i.fillStyle=f;const n=h-s.left,o=c-s.top,a=d-h+s.width,r=u-c+s.height;Object.values(t).some((t=>0!==t))?(i.beginPath(),Ce(i,{x:n,y:o,w:a,h:r,radius:t}),i.fill()):i.fillRect(n,o,a,r)}Pe(i,t._pointLabels[n],a,r+o.lineHeight/2,o,{color:e.color,textAlign:l,textBaseline:"middle"})}}(this,n),s.display&&this.ticks.forEach(((t,e)=>{if(0!==e){a=this.getDistanceFromCenterForValue(t.value);!function(t,e,i,s){const n=t.ctx,o=e.circular,{color:a,lineWidth:r}=e;!o&&!s||!a||!r||i<0||(n.save(),n.strokeStyle=a,n.lineWidth=r,n.setLineDash(e.borderDash),n.lineDashOffset=e.borderDashOffset,n.beginPath(),la(t,i,o,s),n.closePath(),n.stroke(),n.restore())}(this,s.setContext(this.getContext(e-1)),a,n)}})),i.display){for(t.save(),o=n-1;o>=0;o--){const s=i.setContext(this.getPointLabelContext(o)),{color:n,lineWidth:l}=s;l&&n&&(t.lineWidth=l,t.strokeStyle=n,t.setLineDash(s.borderDash),t.lineDashOffset=s.borderDashOffset,a=this.getDistanceFromCenterForValue(e.ticks.reverse?this.min:this.max),r=this.getPointPosition(o,a),t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(r.x,r.y),t.stroke())}t.restore()}}drawBorder(){}drawLabels(){const t=this.ctx,e=this.options,i=e.ticks;if(!i.display)return;const s=this.getIndexAngle(0);let n,o;t.save(),t.translate(this.xCenter,this.yCenter),t.rotate(s),t.textAlign="center",t.textBaseline="middle",this.ticks.forEach(((s,a)=>{if(0===a&&!e.reverse)return;const r=i.setContext(this.getContext(a)),l=ui(r.font);if(n=this.getDistanceFromCenterForValue(this.ticks[a].value),r.showLabelBackdrop){t.font=l.string,o=t.measureText(s.label).width,t.fillStyle=r.backdropColor;const e=di(r.backdropPadding);t.fillRect(-o/2-e.left,-n-l.size/2-e.top,o+e.width,l.size+e.height)}Pe(t,s.label,0,-n,l,{color:r.color})})),t.restore()}drawTitle(){}}ha.id="radialLinear",ha.defaults={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,lineWidth:1,borderDash:[],borderDashOffset:0},grid:{circular:!1},startAngle:0,ticks:{showLabelBackdrop:!0,callback:Ts.formatters.numeric},pointLabels:{backdropColor:void 0,backdropPadding:2,display:!0,font:{size:10},callback:t=>t,padding:5,centerPointLabels:!1}},ha.defaultRoutes={"angleLines.color":"borderColor","pointLabels.color":"color","ticks.color":"color"},ha.descriptors={angleLines:{_fallback:"grid"}};const ca={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},da=Object.keys(ca);function ua(t,e){return t-e}function fa(t,e){if(U(e))return null;const i=t._adapter,{parser:s,round:n,isoWeekday:o}=t._parseOpts;let a=e;return"function"==typeof s&&(a=s(a)),K(a)||(a="string"==typeof s?i.parse(a,s):i.parse(a)),null===a?null:(n&&(a="week"!==n||!Wt(o)&&!0!==o?i.startOf(a,n):i.startOf(a,"isoWeek",o)),+a)}function ga(t,e,i,s){const n=da.length;for(let o=da.indexOf(t);o<n-1;++o){const t=ca[da[o]],n=t.steps?t.steps:Number.MAX_SAFE_INTEGER;if(t.common&&Math.ceil((i-e)/(n*t.size))<=s)return da[o]}return da[n-1]}function pa(t,e,i){if(i){if(i.length){const{lo:s,hi:n}=vt(i,e);t[i[s]>=e?i[s]:i[n]]=!0}}else t[e]=!0}function ma(t,e,i){const s=[],n={},o=e.length;let a,r;for(a=0;a<o;++a)r=e[a],n[r]=a,s.push({value:r,major:!1});return 0!==o&&i?function(t,e,i,s){const n=t._adapter,o=+n.startOf(e[0].value,s),a=e[e.length-1].value;let r,l;for(r=o;r<=a;r=+n.add(r,1,s))l=i[r],l>=0&&(e[l].major=!0);return e}(t,s,n,i):s}class ba extends Ns{constructor(t){super(t),this._cache={data:[],labels:[],all:[]},this._unit="day",this._majorUnit=void 0,this._offsets={},this._normalized=!1,this._parseOpts=void 0}init(t,e){const i=t.time||(t.time={}),s=this._adapter=new xn._date(t.adapters.date);rt(i.displayFormats,s.formats()),this._parseOpts={parser:i.parser,round:i.round,isoWeekday:i.isoWeekday},super.init(t),this._normalized=e.normalized}parse(t,e){return void 0===t?null:fa(this,t)}beforeLayout(){super.beforeLayout(),this._cache={data:[],labels:[],all:[]}}determineDataLimits(){const t=this.options,e=this._adapter,i=t.time.unit||"day";let{min:s,max:n,minDefined:o,maxDefined:a}=this.getUserBounds();function r(t){o||isNaN(t.min)||(s=Math.min(s,t.min)),a||isNaN(t.max)||(n=Math.max(n,t.max))}o&&a||(r(this._getLabelBounds()),"ticks"===t.bounds&&"labels"===t.ticks.source||r(this.getMinMax(!1))),s=K(s)&&!isNaN(s)?s:+e.startOf(Date.now(),i),n=K(n)&&!isNaN(n)?n:+e.endOf(Date.now(),i)+1,this.min=Math.min(s,n-1),this.max=Math.max(s+1,n)}_getLabelBounds(){const t=this.getLabelTimestamps();let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return t.length&&(e=t[0],i=t[t.length-1]),{min:e,max:i}}buildTicks(){const t=this.options,e=t.time,i=t.ticks,s="labels"===i.source?this.getLabelTimestamps():this._generate();"ticks"===t.bounds&&s.length&&(this.min=this._userMin||s[0],this.max=this._userMax||s[s.length-1]);const n=this.min,o=kt(s,n,this.max);return this._unit=e.unit||(i.autoSkip?ga(e.minUnit,this.min,this.max,this._getLabelCapacity(n)):function(t,e,i,s,n){for(let o=da.length-1;o>=da.indexOf(i);o--){const i=da[o];if(ca[i].common&&t._adapter.diff(n,s,i)>=e-1)return i}return da[i?da.indexOf(i):0]}(this,o.length,e.minUnit,this.min,this.max)),this._majorUnit=i.major.enabled&&"year"!==this._unit?function(t){for(let e=da.indexOf(t)+1,i=da.length;e<i;++e)if(ca[da[e]].common)return da[e]}(this._unit):void 0,this.initOffsets(s),t.reverse&&o.reverse(),ma(this,o,this._majorUnit)}afterAutoSkip(){this.options.offsetAfterAutoskip&&this.initOffsets(this.ticks.map((t=>+t.value)))}initOffsets(t){let e,i,s=0,n=0;this.options.offset&&t.length&&(e=this.getDecimalForValue(t[0]),s=1===t.length?1-e:(this.getDecimalForValue(t[1])-e)/2,i=this.getDecimalForValue(t[t.length-1]),n=1===t.length?i:(i-this.getDecimalForValue(t[t.length-2]))/2);const o=t.length<3?.5:.25;s=Qt(s,0,o),n=Qt(n,0,o),this._offsets={start:s,end:n,factor:1/(s+1+n)}}_generate(){const t=this._adapter,e=this.min,i=this.max,s=this.options,n=s.time,o=n.unit||ga(n.minUnit,e,i,this._getLabelCapacity(e)),a=Z(n.stepSize,1),r="week"===o&&n.isoWeekday,l=Wt(r)||!0===r,h={};let c,d,u=e;if(l&&(u=+t.startOf(u,"isoWeek",r)),u=+t.startOf(u,l?"day":o),t.diff(i,e,o)>1e5*a)throw new Error(e+" and "+i+" are too far apart with stepSize of "+a+" "+o);const f="data"===s.ticks.source&&this.getDataTimestamps();for(c=u,d=0;c<i;c=+t.add(c,a,o),d++)pa(h,c,f);return c!==i&&"ticks"!==s.bounds&&1!==d||pa(h,c,f),Object.keys(h).sort(((t,e)=>t-e)).map((t=>+t))}getLabelForValue(t){const e=this._adapter,i=this.options.time;return i.tooltipFormat?e.format(t,i.tooltipFormat):e.format(t,i.displayFormats.datetime)}_tickFormatFunction(t,e,i,s){const n=this.options,o=n.time.displayFormats,a=this._unit,r=this._majorUnit,l=a&&o[a],h=r&&o[r],c=i[e],d=r&&h&&c&&c.major,u=this._adapter.format(t,s||(d?h:l)),f=n.ticks.callback;return f?tt(f,[u,e,i],this):u}generateTickLabels(t){let e,i,s;for(e=0,i=t.length;e<i;++e)s=t[e],s.label=this._tickFormatFunction(s.value,e,t)}getDecimalForValue(t){return null===t?NaN:(t-this.min)/(this.max-this.min)}getPixelForValue(t){const e=this._offsets,i=this.getDecimalForValue(t);return this.getPixelForDecimal((e.start+i)*e.factor)}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return this.min+i*(this.max-this.min)}_getLabelSize(t){const e=this.options.ticks,i=this.ctx.measureText(t).width,s=Yt(this.isHorizontal()?e.maxRotation:e.minRotation),n=Math.cos(s),o=Math.sin(s),a=this._resolveTickFontOptions(0).size;return{w:i*n+a*o,h:i*o+a*n}}_getLabelCapacity(t){const e=this.options.time,i=e.displayFormats,s=i[e.unit]||i.millisecond,n=this._tickFormatFunction(t,0,ma(this,[t],this._majorUnit),s),o=this._getLabelSize(n),a=Math.floor(this.isHorizontal()?this.width/o.w:this.height/o.h)-1;return a>0?a:1}getDataTimestamps(){let t,e,i=this._cache.data||[];if(i.length)return i;const s=this.getMatchingVisibleMetas();if(this._normalized&&s.length)return this._cache.data=s[0].controller.getAllParsedValues(this);for(t=0,e=s.length;t<e;++t)i=i.concat(s[t].controller.getAllParsedValues(this));return this._cache.data=this.normalize(i)}getLabelTimestamps(){const t=this._cache.labels||[];let e,i;if(t.length)return t;const s=this.getLabels();for(e=0,i=s.length;e<i;++e)t.push(fa(this,s[e]));return this._cache.labels=this._normalized?t:this.normalize(t)}normalize(t){return Ct(t.sort(ua))}}function xa(t,e,i){let s,n,o,a,r=0,l=t.length-1;i?(e>=t[r].pos&&e<=t[l].pos&&({lo:r,hi:l}=wt(t,"pos",e)),({pos:s,time:o}=t[r]),({pos:n,time:a}=t[l])):(e>=t[r].time&&e<=t[l].time&&({lo:r,hi:l}=wt(t,"time",e)),({time:s,pos:o}=t[r]),({time:n,pos:a}=t[l]));const h=n-s;return h?o+(a-o)*(e-s)/h:o}ba.id="time",ba.defaults={bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{source:"auto",major:{enabled:!1}}};class _a extends ba{constructor(t){super(t),this._table=[],this._minPos=void 0,this._tableRange=void 0}initOffsets(){const t=this._getTimestampsForTable(),e=this._table=this.buildLookupTable(t);this._minPos=xa(e,this.min),this._tableRange=xa(e,this.max)-this._minPos,super.initOffsets(t)}buildLookupTable(t){const{min:e,max:i}=this,s=[],n=[];let o,a,r,l,h;for(o=0,a=t.length;o<a;++o)l=t[o],l>=e&&l<=i&&s.push(l);if(s.length<2)return[{time:e,pos:0},{time:i,pos:1}];for(o=0,a=s.length;o<a;++o)h=s[o+1],r=s[o-1],l=s[o],Math.round((h+r)/2)!==l&&n.push({time:l,pos:o/(a-1)});return n}_getTimestampsForTable(){let t=this._cache.all||[];if(t.length)return t;const e=this.getDataTimestamps(),i=this.getLabelTimestamps();return t=e.length&&i.length?this.normalize(e.concat(i)):e.length?e:i,t=this._cache.all=t,t}getDecimalForValue(t){return(xa(this._table,t)-this._minPos)/this._tableRange}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return xa(this._table,i*this._tableRange+this._minPos,!0)}}_a.id="timeseries",_a.defaults=ba.defaults;var ya=Object.freeze({__proto__:null,CategoryScale:Ko,LinearScale:Jo,LogarithmicScale:ta,RadialLinearScale:ha,TimeScale:ba,TimeSeriesScale:_a});return fn.register(In,ya,ao,Xo),fn.helpers={...Di},fn._adapters=xn,fn.Animation=gs,fn.Animations=ms,fn.animator=a,fn.controllers=Hs.controllers.items,fn.DatasetController=Cs,fn.Element=Os,fn.elements=ao,fn.Interaction=Ei,fn.layouts=Xi,fn.platforms=ds,fn.Scale=Ns,fn.Ticks=Ts,Object.assign(fn,In,ya,ao,Xo,ds),fn.Chart=fn,"undefined"!=typeof window&&(window.Chart=fn),fn}));
cookie-notice.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Cookie Notice & Compliance for GDPR / CCPA
4
  Description: Cookie Notice allows you to you elegantly inform users that your site uses cookies and helps you comply with GDPR, CCPA and other data privacy laws.
5
- Version: 2.3.1
6
  Author: Hu-manity.co
7
  Author URI: https://hu-manity.co/
8
  Plugin URI: https://hu-manity.co/
@@ -29,18 +29,34 @@ if ( ! defined( 'ABSPATH' ) )
29
  * Cookie Notice class.
30
  *
31
  * @class Cookie_Notice
32
- * @version 2.3.1
33
  */
34
  class Cookie_Notice {
35
 
36
  private $status = '';
 
 
 
37
  private $app_dashboard_url = 'https://app.hu-manity.co/#/en/cc/dashboard';
 
 
 
 
 
 
 
 
 
 
 
38
 
39
  /**
40
  * @var $defaults
41
  */
42
- public $defaults = array(
43
- 'general' => array(
 
 
44
  'app_id' => '',
45
  'app_key' => '',
46
  'app_blocking' => true,
@@ -68,53 +84,55 @@ class Cookie_Notice {
68
  'on_scroll' => false,
69
  'on_scroll_offset' => 100,
70
  'on_click' => false,
71
- 'colors' => array(
72
  'text' => '#fff',
73
  'button' => '#00a99d',
74
  'bar' => '#32323a',
75
  'bar_opacity' => 100
76
- ),
77
- 'see_more_opt' => array(
78
  'text' => '',
79
  'link_type' => 'page',
80
  'id' => 0,
81
  'link' => '',
82
  'sync' => false
83
- ),
84
- 'script_placement' => 'header',
85
- 'translate' => true,
86
- 'deactivation_delete' => false,
87
- 'update_version' => 5,
88
- 'update_notice' => true,
89
- 'update_delay_date' => 0,
90
- 'update_threshold_date' => 0
91
- ),
92
- 'version' => '2.3.1'
93
- );
94
- private $deactivaion_url = '';
95
-
96
- private static $_instance;
97
 
98
  /**
99
  * Disable object cloning.
 
 
100
  */
101
  public function __clone() {}
102
 
103
  /**
104
  * Disable unserializing of the class.
 
 
105
  */
106
  public function __wakeup() {}
107
 
108
  /**
109
  * Main plugin instance.
110
- *
111
  * @return object
112
  */
113
  public static function instance() {
114
  if ( self::$_instance === null ) {
115
  self::$_instance = new self();
116
 
117
- add_action( 'plugins_loaded', array( self::$_instance, 'load_textdomain' ) );
118
 
119
  self::$_instance->includes();
120
 
@@ -132,46 +150,190 @@ class Cookie_Notice {
132
 
133
  /**
134
  * Constructor.
 
 
135
  */
136
  public function __construct() {
137
- register_activation_hook( __FILE__, array( $this, 'activation' ) );
138
- register_deactivation_hook( __FILE__, array( $this, 'deactivation' ) );
139
-
 
 
 
140
  // get options
141
- $options = get_option( 'cookie_notice_options', $this->defaults['general'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  // check legacy parameters
144
- $options = $this->check_legacy_params( $options, array( 'refuse_opt', 'on_scroll', 'on_click', 'deactivation_delete', 'see_more' ) );
145
 
146
  // merge old options with new ones
147
- $this->options = array(
148
- 'general' => $this->multi_array_merge( $this->defaults['general'], $options )
149
- );
150
 
151
  if ( ! isset( $this->options['general']['see_more_opt']['sync'] ) )
152
  $this->options['general']['see_more_opt']['sync'] = $this->defaults['general']['see_more_opt']['sync'];
153
-
154
- // actions
155
- add_action( 'plugins_loaded', array( $this, 'set_status' ) );
156
- add_action( 'init', array( $this, 'register_shortcodes' ) );
157
- add_action( 'init', array( $this, 'wpsc_add_cookie' ) );
158
- add_action( 'admin_init', array( $this, 'update_notice' ) );
159
- add_action( 'wp_ajax_cn_dismiss_notice', array( $this, 'ajax_dismiss_admin_notice' ) );
160
- add_action( 'admin_footer', array( $this, 'deactivate_plugin_template' ) );
161
- add_action( 'wp_ajax_cn-deactivate-plugin', array( $this, 'deactivate_plugin' ) );
162
- add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
163
 
164
- // filters
165
- add_filter( 'plugin_action_links', array( $this, 'plugin_action_links' ), 10, 2 );
 
 
 
 
 
 
 
 
166
  }
167
-
168
  /**
169
  * Set plugin status.
 
 
170
  */
171
  public function set_status() {
172
- $status = get_option( 'cookie_notice_status', '' );
173
-
174
- $this->status = ! empty( $status ) && in_array( $status, array( 'active', 'pending' ), true ) ? $status : false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  }
176
 
177
  /**
@@ -180,114 +342,270 @@ class Cookie_Notice {
180
  * @return void
181
  */
182
  private function includes() {
183
- include_once( plugin_dir_path( __FILE__ ) . 'includes/bot-detect.php' );
184
- include_once( plugin_dir_path( __FILE__ ) . 'includes/dashboard.php' );
185
- include_once( plugin_dir_path( __FILE__ ) . 'includes/frontend.php' );
186
- include_once( plugin_dir_path( __FILE__ ) . 'includes/functions.php' );
187
- include_once( plugin_dir_path( __FILE__ ) . 'includes/settings.php' );
188
- include_once( plugin_dir_path( __FILE__ ) . 'includes/welcome.php' );
189
- include_once( plugin_dir_path( __FILE__ ) . 'includes/welcome-api.php' );
190
- include_once( plugin_dir_path( __FILE__ ) . 'includes/welcome-frontend.php' );
 
 
 
191
  }
192
-
193
  /**
194
  * Load textdomain.
 
 
195
  */
196
  public function load_textdomain() {
197
- load_plugin_textdomain( 'cookie-notice', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
198
  }
199
-
200
  /**
201
- * Activate the plugin.
 
 
 
 
 
202
  */
203
- public function activation() {
204
- add_option( 'cookie_notice_options', $this->defaults['general'], '', 'no' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  }
206
 
207
  /**
208
- * Deactivate the plugin.
 
 
 
209
  */
210
- public function deactivation() {
211
- if ( $this->options['general']['deactivation_delete'] === true ) {
 
 
212
  delete_option( 'cookie_notice_options' );
213
- delete_option( 'cookie_notice_version' );
214
  delete_option( 'cookie_notice_status' );
215
  delete_option( 'cookie_notice_app_analytics' );
216
-
 
 
217
  delete_transient( 'cookie_notice_compliance_cache' );
218
  }
219
-
220
- // remove WP Super Cache cookie
221
  $this->wpsc_delete_cookie();
222
  }
223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  /**
225
  * Update notice.
226
- *
227
  * @return void
228
  */
229
  public function update_notice() {
230
  if ( ! current_user_can( 'install_plugins' ) )
231
  return;
232
-
233
  // bail an ajax
234
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
235
  return;
236
-
237
- $current_update = 6;
238
-
 
 
239
  // get current database version
240
- $current_db_version = get_option( 'cookie_notice_version', '1.0.0' );
241
-
 
 
 
242
  if ( version_compare( $current_db_version, $this->defaults['version'], '<' ) && $this->options['general']['update_version'] < $current_update ) {
243
  // check version, if update version is lower than plugin version, set update notice to true
244
- $this->options['general'] = wp_parse_args( array( 'update_version' => $current_update, 'update_notice' => true ), $this->options['general'] );
 
245
 
246
- update_option( 'cookie_notice_options', $this->options['general'] );
247
-
248
- // update plugin version
249
- update_option( 'cookie_notice_version', $this->defaults['version'], false );
 
 
 
 
 
 
 
 
 
 
 
250
  }
251
-
252
  // if visiting settings, mark notice as read
253
  if ( ! empty( $_GET['page'] ) && $_GET['page'] === 'cookie-notice' && ! empty( $_GET['welcome'] ) ) {
254
- $this->options['general'] = wp_parse_args( array( 'update_notice' => false ), $this->options['general'] );
255
- update_option( 'cookie_notice_options', $this->options['general'] );
 
 
 
 
 
 
256
  }
257
-
 
 
 
 
 
 
258
  // show notice, if no compliance only
259
- if ( $this->options['general']['update_notice'] === true && empty( $this->status ) ) {
260
- // set_transient( 'cn_show_welcome', 1 );
261
- $this->add_notice( '<div class="cn-notice-text"><h2>' . __( 'Compliance fines exceeded &euro;1.3 BILLION in 2021. Avoid the risk by making sure your website complies with the latest cookie consent laws.', 'cookie-notice' ) . '</h2><p>' . __( 'Run compliance check to learn if your website complies with the latest consent record storage and cookie blocking requirements.', 'cookie-notice' ) . '</p><p class="cn-notice-actions"><a href="' . admin_url( 'admin.php' ) . '?page=cookie-notice&welcome=1' . '" class="button button-primary cn-button">' . __( 'Run Compliance Check', 'cookie-notice' ) . '</a> <a href="#" class="button-link cn-notice-dismiss">' . __( 'Dismiss Notice', 'cookie-notice' ) . '</a></p></div>', 'error', 'div' );
262
  }
263
-
264
  // show treshold limit warning, compliance only
265
- if ( $this->status === 'active' ) {
266
  // get analytics data options
267
- $analytics = get_option( 'cookie_notice_app_analytics' );
268
-
269
- if ( $analytics ) {
 
 
 
 
 
 
 
 
270
  // cycle usage data
271
- $cycle_usage = array(
272
- 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
273
- 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0,
274
- 'days_to_go' => ! empty( $analytics['cycleUsage']->daysToGo ) ? (int) $analytics['cycleUsage']->daysToGo : 0,
275
- 'start_date' => ! empty( $analytics['cycleUsage']->startDate ) ? strtotime( $analytics['cycleUsage']->startDate ) : '',
276
- 'end_date' => ! empty( $analytics['cycleUsage']->endDate ) ? strtotime( $analytics['cycleUsage']->endDate ) : '',
277
- 'last_updated' => ! empty( $analytics['lastUpdated'] ) ? strtotime( $analytics['lastUpdated'] ) : strtotime( current_time( 'mysql' ) )
278
- );
279
-
280
  // if threshold in use
281
  if ( $cycle_usage['threshold'] ) {
282
  // if threshold exceeded and there was no notice before
283
- if ( $cycle_usage['visits'] >= $cycle_usage['threshold'] && $cycle_usage['last_updated'] < $cycle_usage['end_date'] && $this->options['general']['update_threshold_date'] < $cycle_usage['end_date'] ) {
284
  $date_format = get_option( 'date_format' );
285
-
286
- $upgrade_link = $this->app_dashboard_url . '?app-id=' . $this->options['general']['app_id'] . '&open-modal=payment';
287
  $threshold = $cycle_usage['threshold'];
288
- $cycle_date = date_i18n( $date_format, $cycle_usage['end_date'] );
289
-
290
- $this->add_notice( '<div class="cn-notice-text" data-delay="' . $cycle_usage['end_date'] . '"><h2>' . __( 'Cookie Compliance Warning', 'cookie-notice') . '</h2><p>' . sprintf( __( 'Your website has reached the <b>%1$s visits usage limit for the Cookie Compliance Free Plan</b>. Compliance services such as Consent Record Storage, Autoblocking, and Consent Analytics have been deactivated until current usage cycle ends on %2$s.', 'cookie-notice' ), $threshold, $cycle_date ) . '<br>' . sprintf( __( 'To reactivate compliance services now, <a href="%s" target="_blank">upgrade your domain to a Pro plan.</a>', 'cookie-notice' ) . '</p></div>', $upgrade_link ), 'cn-threshold error is-dismissible', 'div' );
291
  }
292
  }
293
  }
@@ -295,26 +613,28 @@ class Cookie_Notice {
295
  }
296
 
297
  /**
298
- * Add admin notices.
299
- *
300
  * @param string $html
301
  * @param string $status
302
- * @param bool $paragraph
 
303
  */
304
  private function add_notice( $html = '', $status = 'error', $container = '' ) {
305
- $this->notices[] = array(
306
- 'html' => $html,
307
- 'status' => $status,
308
- 'container' => ( ! empty( $container ) && in_array( $container, array( 'p', 'div' ) ) ? $container : '' )
309
- );
310
-
311
- add_action( 'admin_notices', array( $this, 'display_notice'), 0 );
 
312
  }
313
 
314
  /**
315
  * Print admin notices.
316
- *
317
- * @return mixed
318
  */
319
  public function display_notice() {
320
  foreach( $this->notices as $notice ) {
@@ -329,6 +649,8 @@ class Cookie_Notice {
329
 
330
  /**
331
  * Dismiss admin notice.
 
 
332
  */
333
  public function ajax_dismiss_admin_notice() {
334
  if ( ! current_user_can( 'install_plugins' ) )
@@ -336,38 +658,48 @@ class Cookie_Notice {
336
 
337
  if ( wp_verify_nonce( $_REQUEST['nonce'], 'cn_dismiss_notice' ) ) {
338
  $notice_action = empty( $_REQUEST['notice_action'] ) || $_REQUEST['notice_action'] === 'dismiss' ? 'dismiss' : sanitize_text_field( $_REQUEST['notice_action'] );
 
339
 
340
  switch ( $notice_action ) {
341
- // delay notice
342
  case 'threshold':
343
  // set delay period last cycle day
344
  $delay = isset( $_REQUEST['param'] ) ? (int) $_REQUEST['param'] : 0;
345
- $this->options['general'] = wp_parse_args( array( 'update_threshold_date' => $delay + DAY_IN_SECONDS ), $this->options['general'] );
346
- update_option( 'cookie_notice_options', $this->options['general'] );
 
 
 
 
 
 
347
  break;
348
-
349
  // delay notice
350
  case 'delay':
351
  // set delay period to 1 week from now
352
- $this->options['general'] = wp_parse_args( array( 'update_delay_date' => time() + 1209600 ), $this->options['general'] );
353
- update_option( 'cookie_notice_options', $this->options['general'] );
354
- break;
355
-
356
- // delay notice
357
- case 'approve':
358
- // hide notice
359
- $this->options['general'] = wp_parse_args( array( 'update_notice' => false ), $this->options['general'] );
360
- $this->options['general'] = wp_parse_args( array( 'update_delay_date' => 0 ), $this->options['general'] );
361
  // update options
362
- update_option( 'cookie_notice_options', $this->options['general'] );
 
 
 
363
  break;
364
 
365
  // hide notice
 
366
  default:
367
- $this->options['general'] = wp_parse_args( array( 'update_notice' => false ), $this->options['general'] );
368
- $this->options['general'] = wp_parse_args( array( 'update_delay_date' => 0 ), $this->options['general'] );
369
 
370
- update_option( 'cookie_notice_options', $this->options['general'] );
 
 
 
 
 
 
371
  }
372
  }
373
 
@@ -380,9 +712,9 @@ class Cookie_Notice {
380
  * @return void
381
  */
382
  public function register_shortcodes() {
383
- add_shortcode( 'cookies_accepted', array( $this, 'cookies_accepted_shortcode' ) );
384
- add_shortcode( 'cookies_revoke', array( $this, 'cookies_revoke_shortcode' ) );
385
- add_shortcode( 'cookies_policy_link', array( $this, 'cookies_policy_link_shortcode' ) );
386
  }
387
 
388
  /**
@@ -390,7 +722,7 @@ class Cookie_Notice {
390
  *
391
  * @param array $args
392
  * @param mixed $content
393
- * @return mixed
394
  */
395
  public function cookies_accepted_shortcode( $args, $content ) {
396
  if ( $this->cookies_accepted() ) {
@@ -408,21 +740,28 @@ class Cookie_Notice {
408
  }
409
 
410
  /**
411
- * Register cookies accepted shortcode.
412
  *
413
  * @param array $args
414
  * @param mixed $content
415
- * @return mixed
416
  */
417
  public function cookies_revoke_shortcode( $args, $content ) {
418
  // get options
419
  $options = $this->options['general'];
420
 
 
 
 
 
 
 
 
421
  // defaults
422
- $defaults = array(
423
  'title' => $options['revoke_text'],
424
  'class' => $options['css_class']
425
- );
426
 
427
  // combine shortcode arguments
428
  $args = shortcode_atts( $defaults, $args );
@@ -431,9 +770,9 @@ class Cookie_Notice {
431
  $args['class'] = esc_attr( $args['class'] );
432
 
433
  if ( Cookie_Notice()->get_status() === 'active' )
434
- $shortcode = '<a href="#" class="cn-revoke-cookie cn-button-inline cn-revoke-inline' . ( $args['class'] !== '' ? ' ' . $args['class'] : '' ) . '" title="' . esc_html( $args['title'] ) . '" data-hu-action="cookies-notice-revoke">' . esc_html( $args['title'] ) . '</a>';
435
  else
436
- $shortcode = '<a href="#" class="cn-revoke-cookie cn-button-inline cn-revoke-inline' . ( $args['class'] !== '' ? ' ' . $args['class'] : '' ) . '" title="' . esc_html( $args['title'] ) . '">' . esc_html( $args['title'] ) . '</a>';
437
 
438
  return $shortcode;
439
  }
@@ -449,12 +788,50 @@ class Cookie_Notice {
449
  // get options
450
  $options = $this->options['general'];
451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
  // defaults
453
- $defaults = array(
454
  'title' => esc_html( $options['see_more_opt']['text'] !== '' ? $options['see_more_opt']['text'] : '&#x279c;' ),
455
- 'link' => ( $options['see_more_opt']['link_type'] === 'custom' ? esc_url( $options['see_more_opt']['link'] ) : get_permalink( $options['see_more_opt']['id'] ) ),
456
  'class' => esc_attr( $options['css_class'] )
457
- );
458
 
459
  // combine shortcode arguments
460
  $args = shortcode_atts( $defaults, $args );
@@ -466,26 +843,27 @@ class Cookie_Notice {
466
 
467
  /**
468
  * Check if cookies are accepted.
469
- *
470
  * @return bool
471
  */
472
  public static function cookies_accepted() {
473
  if ( Cookie_Notice()->get_status() === 'active' ) {
474
- $cookies = isset( $_COOKIE['hu-consent'] ) ? json_decode( stripslashes( $_COOKIE['hu-consent'] ), true ) : array();
475
-
476
  if ( ! empty( $cookies ) && is_array( $cookies ) ) {
477
  foreach( $cookies as $cookie_name => $cookie_value ) {
478
  switch ( $cookie_name ) {
479
  case 'consent':
480
  $cookies[$cookie_name] = (bool) $cookie_value;
481
  break;
 
482
  default:
483
  $cookies[$cookie_name] = is_array( $cookie_value ) ? array_map( 'sanitize_text_field', $cookie_value ) : sanitize_text_field( $cookie_value );
484
  }
485
  }
486
  }
487
 
488
- $result = ( is_array( $cookies ) && json_last_error() === JSON_ERROR_NONE && ! empty( $cookies['consent'] ) ) ? true : false;
489
  } else
490
  $result = isset( $_COOKIE['cookie_notice_accepted'] ) && $_COOKIE['cookie_notice_accepted'] === 'true';
491
 
@@ -495,7 +873,7 @@ class Cookie_Notice {
495
  /**
496
  * Check if cookies are set.
497
  *
498
- * @return boolean Whether cookies are set
499
  */
500
  public function cookies_set() {
501
  if ( Cookie_Notice()->get_status() === 'active' )
@@ -508,6 +886,8 @@ class Cookie_Notice {
508
 
509
  /**
510
  * Add WP Super Cache cookie.
 
 
511
  */
512
  public function wpsc_add_cookie() {
513
  if ( Cookie_Notice()->get_status() === 'active' )
@@ -518,6 +898,8 @@ class Cookie_Notice {
518
 
519
  /**
520
  * Delete WP Super Cache cookie.
 
 
521
  */
522
  public function wpsc_delete_cookie() {
523
  if ( Cookie_Notice()->get_status() === 'active' )
@@ -525,7 +907,7 @@ class Cookie_Notice {
525
  else
526
  do_action( 'wpsc_delete_cookie', 'cookie_notice_accepted' );
527
  }
528
-
529
  /**
530
  * Enqueue admin scripts and styles.
531
  *
@@ -537,40 +919,54 @@ class Cookie_Notice {
537
  if ( $page === 'plugins.php' ) {
538
  add_thickbox();
539
 
540
- wp_enqueue_script( 'cookie-notice-admin-plugins', plugins_url( '/js/admin-plugins.js', __FILE__ ), array( 'jquery' ), $this->defaults['version'] );
541
 
542
- wp_enqueue_style( 'cookie-notice-admin-plugins', plugins_url( '/css/admin-plugins.css', __FILE__ ), array(), $this->defaults['version'] );
543
 
544
  wp_localize_script(
545
  'cookie-notice-admin-plugins',
546
  'cnArgsPlugins',
547
- array(
548
  'deactivate' => __( 'Cookie Notice & Compliance - Deactivation survey', 'cookie-notice' ),
549
  'nonce' => wp_create_nonce( 'cn-deactivate-plugin' )
550
- )
551
  );
552
  }
553
-
554
  // notice js and css
555
  wp_enqueue_script(
556
- 'cookie-notice-admin-notice', plugins_url( '/js/admin-notice.js', __FILE__ ), array( 'jquery' ), Cookie_Notice()->defaults['version']
557
  );
558
 
559
  wp_localize_script(
560
- 'cookie-notice-admin-notice', 'cnArgsNotice', array(
561
- 'ajaxURL' => admin_url( 'admin-ajax.php' ),
562
- 'nonce' => wp_create_nonce( 'cn_dismiss_notice' ),
563
- )
 
 
 
564
  );
565
 
566
  wp_enqueue_style(
567
- 'cookie-notice-admin-notice', plugins_url( '/css/admin-notice.css', __FILE__ ), array(), Cookie_Notice()->defaults['version']
568
  );
569
  }
570
 
 
 
 
 
 
 
 
 
 
 
 
571
  /**
572
  * Add links to settings page.
573
- *
574
  * @param array $links
575
  * @param string $file
576
  * @return array
@@ -578,12 +974,8 @@ class Cookie_Notice {
578
  public function plugin_action_links( $links, $file ) {
579
  if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
580
  return $links;
581
-
582
- static $plugin;
583
 
584
- $plugin = plugin_basename( __FILE__ );
585
-
586
- if ( $file == $plugin ) {
587
  if ( ! empty( $links['deactivate'] ) ) {
588
  // link already contains class attribute?
589
  if ( preg_match( '/<a.*?class=(\'|")(.*?)(\'|").*?>/is', $links['deactivate'], $result ) === 1 )
@@ -598,20 +990,33 @@ class Cookie_Notice {
598
  }
599
  }
600
 
601
- // put settings link at start
602
- array_unshift( $links, sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php' ) . '?page=cookie-notice', __( 'Settings', 'cookie-notice' ) ) );
 
 
 
603
 
604
- // add add-ons link
605
- if ( empty( $this->status ) )
606
- $links[] = sprintf( '<a href="%s" style="color: #20C19E; font-weight: bold;">%s</a>', admin_url( 'admin.php' ) . '?page=cookie-notice&welcome=1', __( 'Free Upgrade', 'cookie-notice' ) );
 
 
 
 
 
 
 
 
607
  }
608
 
609
  return $links;
610
  }
611
-
612
  /**
613
  * Deactivation modal HTML template.
614
  *
 
 
615
  * @return void
616
  */
617
  public function deactivate_plugin_template() {
@@ -629,7 +1034,7 @@ class Cookie_Notice {
629
  <p><em>' . __( "We're sorry to see you go. Could you please tell us what happened?", 'cookie-notice' ) . '</em></p>
630
  <ul>';
631
 
632
- foreach ( array(
633
  '1' => __( "I couldn't figure out how to make it work.", 'cookie-notice' ),
634
  '2' => __( 'I found another plugin to use for the same task.', 'cookie-notice' ),
635
  '3' => __( 'The Cookie Compliance banner is too big.', 'cookie-notice' ),
@@ -638,12 +1043,12 @@ class Cookie_Notice {
638
  '6' => __( 'The web application user interface is not clear to me.', 'cookie-notice' ),
639
  '7' => __( "Support isn't timely.", 'cookie-notice' ),
640
  '8' => __( 'Other', 'cookie-notice' )
641
- ) as $option => $text ) {
642
- echo '
643
  <li><label><input type="radio" name="cn_deactivation_option" value="' . $option . '" ' . checked( '8', $option, false ) . ' />' . esc_html( $text ) . '</label></li>';
644
  }
645
 
646
- echo '
647
  </ul>
648
  </div>
649
  <div class="cn-deactivation-textarea">
@@ -673,23 +1078,24 @@ class Cookie_Notice {
673
  if ( isset( $_POST['option_id'] ) ) {
674
  $option_id = (int) $_POST['option_id'];
675
  $other = esc_html( $_POST['other'] );
676
-
677
  // avoid fake submissions
678
  if ( $option_id == 8 && $other == '' )
679
  wp_send_json_success();
680
 
681
  wp_remote_post(
682
- 'https://hu-manity.co/wp-json/api/v1/forms/', array(
683
- 'timeout' => 15,
684
- 'blocking' => true,
685
- 'headers' => array(),
686
- 'body' => array(
687
- 'id' => 1,
688
- 'option' => $option_id,
689
- 'other' => $other,
690
- 'referrer' => get_site_url()
691
- )
692
- )
 
693
  );
694
 
695
  wp_send_json_success();
@@ -708,43 +1114,43 @@ class Cookie_Notice {
708
  'cn_refuse_code_allowed_html',
709
  array_merge(
710
  wp_kses_allowed_html( 'post' ),
711
- array(
712
- 'script' => array(
713
- 'type' => array(),
714
- 'src' => array(),
715
- 'charset' => array(),
716
- 'async' => array()
717
- ),
718
- 'noscript' => array(),
719
- 'style' => array(
720
- 'type' => array()
721
- ),
722
- 'iframe' => array(
723
- 'src' => array(),
724
- 'height' => array(),
725
- 'width' => array(),
726
- 'frameborder' => array(),
727
- 'allowfullscreen' => array()
728
- )
729
- )
730
  )
731
  );
732
  }
733
 
734
  /**
735
  * Helper: convert hex color to rgb color.
736
- *
737
  * @param type $color
738
- * @return array
739
  */
740
  public function hex2rgb( $color ) {
741
  if ( $color[0] == '#' )
742
  $color = substr( $color, 1 );
743
 
744
  if ( strlen( $color ) == 6 )
745
- list( $r, $g, $b ) = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
746
  elseif ( strlen( $color ) == 3 )
747
- list( $r, $g, $b ) = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
748
  else
749
  return false;
750
 
@@ -752,13 +1158,13 @@ class Cookie_Notice {
752
  $g = hexdec( $g );
753
  $b = hexdec( $b );
754
 
755
- return array( $r, $g, $b );
756
  }
757
-
758
  /**
759
- * Helper: Convert undersocores to CamelCase/
760
- *
761
- * @param type $string
762
  * @param bool $capitalize_first_char
763
  * @return string
764
  */
@@ -771,7 +1177,7 @@ class Cookie_Notice {
771
 
772
  return $str;
773
  }
774
-
775
  /**
776
  * Check legacy parameters that were yes/no strings.
777
  *
@@ -797,17 +1203,17 @@ class Cookie_Notice {
797
  * $siblings examples: array( '=>', 'only_first_level', 'first_level=>second_level', 'first_key=>next_key=>sibling' ) and so on.
798
  * Single '=>' means that all siblings of the highest level will be kept in the final array.
799
  *
800
- * @param array $default Array with defaults values
801
  * @param array $array Array to merge
802
  * @param boolean|array $siblings Whether to allow "string" siblings to copy from $array if they do not exist in $defaults, false otherwise
803
- * @return array Merged arrays
804
  */
805
  public function multi_array_merge( $defaults, $array, $siblings = false ) {
806
  // make a copy for better performance and to prevent $default override in foreach
807
  $copy = $defaults;
808
 
809
  // prepare siblings for recursive deeper level
810
- $new_siblings = array();
811
 
812
  // allow siblings?
813
  if ( ! empty( $siblings ) && is_array( $siblings ) ) {
@@ -833,7 +1239,7 @@ class Cookie_Notice {
833
 
834
  // more than one sibling child?
835
  if ( count( $ex ) > 1 )
836
- $new_siblings[$ex[0]] = array( substr_replace( $sibling, '', 0, strlen( $ex[0] . '=>' ) ) );
837
  // no more sibling children
838
  else
839
  $new_siblings[$ex[0]] = false;
@@ -865,24 +1271,15 @@ class Cookie_Notice {
865
 
866
  return $copy;
867
  }
868
-
869
- /**
870
- * Get plugin mode
871
- *
872
- * @return type
873
- */
874
- public function get_status() {
875
- return $this->status; // notice, active, pending etc.
876
- }
877
 
878
  /**
879
- * Indicate if current page is the Cookie Policy page
880
  *
881
  * @return bool
882
  */
883
  public function is_cookie_policy_page() {
884
  $see_more = $this->options['general']['see_more_opt'];
885
-
886
  if ( $see_more['link_type'] !== 'page' )
887
  return false;
888
 
@@ -893,7 +1290,6 @@ class Cookie_Notice {
893
 
894
  return $current_page->post_name === $cp_slug;
895
  }
896
-
897
  }
898
 
899
  /**
@@ -909,4 +1305,4 @@ function Cookie_Notice() {
909
  return $instance;
910
  }
911
 
912
- $cookie_notice = Cookie_Notice();
2
  /*
3
  Plugin Name: Cookie Notice & Compliance for GDPR / CCPA
4
  Description: Cookie Notice allows you to you elegantly inform users that your site uses cookies and helps you comply with GDPR, CCPA and other data privacy laws.
5
+ Version: 2.4.0
6
  Author: Hu-manity.co
7
  Author URI: https://hu-manity.co/
8
  Plugin URI: https://hu-manity.co/
29
  * Cookie Notice class.
30
  *
31
  * @class Cookie_Notice
32
+ * @version 2.4.0
33
  */
34
  class Cookie_Notice {
35
 
36
  private $status = '';
37
+ private $x_api_key = 'hudft60djisdusdjwek';
38
+ private $app_host_url = 'https://app.hu-manity.co';
39
+ private $app_login_url = 'https://app.hu-manity.co/#/en/cc2/login';
40
  private $app_dashboard_url = 'https://app.hu-manity.co/#/en/cc/dashboard';
41
+ private $account_api_url = 'https://account-api.hu-manity.co';
42
+ private $designer_api_url = 'https://designer-api.hu-manity.co';
43
+ private $transactional_api_url = 'https://transactional-api.hu-manity.co';
44
+ private $app_widget_url = '//cdn.hu-manity.co/hu-banner.min.js';
45
+ private $deactivaion_url = '';
46
+ private $plugin_basename = '';
47
+ private $network_admin = false;
48
+ private $plugin_network_active = false;
49
+ private static $_instance;
50
+ public $options = [];
51
+ public $network_options = [];
52
 
53
  /**
54
  * @var $defaults
55
  */
56
+ public $defaults = [
57
+ 'general' => [
58
+ 'global_override' => false,
59
+ 'global_cookie' => false,
60
  'app_id' => '',
61
  'app_key' => '',
62
  'app_blocking' => true,
84
  'on_scroll' => false,
85
  'on_scroll_offset' => 100,
86
  'on_click' => false,
87
+ 'colors' => [
88
  'text' => '#fff',
89
  'button' => '#00a99d',
90
  'bar' => '#32323a',
91
  'bar_opacity' => 100
92
+ ],
93
+ 'see_more_opt' => [
94
  'text' => '',
95
  'link_type' => 'page',
96
  'id' => 0,
97
  'link' => '',
98
  'sync' => false
99
+ ],
100
+ 'script_placement' => 'header',
101
+ 'translate' => true,
102
+ 'deactivation_delete' => false,
103
+ 'update_version' => 6,
104
+ 'update_notice' => true,
105
+ 'update_notice_diss' => false,
106
+ 'update_delay_date' => 0,
107
+ 'update_threshold_date' => 0
108
+ ],
109
+ 'version' => '2.4.0'
110
+ ];
 
 
111
 
112
  /**
113
  * Disable object cloning.
114
+ *
115
+ * @return void
116
  */
117
  public function __clone() {}
118
 
119
  /**
120
  * Disable unserializing of the class.
121
+ *
122
+ * @return void
123
  */
124
  public function __wakeup() {}
125
 
126
  /**
127
  * Main plugin instance.
128
+ *
129
  * @return object
130
  */
131
  public static function instance() {
132
  if ( self::$_instance === null ) {
133
  self::$_instance = new self();
134
 
135
+ add_action( 'init', [ self::$_instance, 'load_textdomain' ] );
136
 
137
  self::$_instance->includes();
138
 
150
 
151
  /**
152
  * Constructor.
153
+ *
154
+ * @return void
155
  */
156
  public function __construct() {
157
+ register_activation_hook( __FILE__, [ $this, 'activation' ] );
158
+ register_deactivation_hook( __FILE__, [ $this, 'deactivation' ] );
159
+
160
+ // set network data
161
+ $this->set_network_data();
162
+
163
  // get options
164
+ if ( is_multisite() ) {
165
+ // get network options
166
+ $this->network_options = get_site_option( 'cookie_notice_options', $this->defaults['general'] );
167
+
168
+ if ( $this->is_network_admin() ) {
169
+ $options = $this->network_options;
170
+ } else {
171
+ // settings page?
172
+ if ( is_admin() && isset( $_GET['page'] ) && $_GET['page'] === 'cookie-notice' ) {
173
+ // get current url path
174
+ $url_path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
175
+
176
+ if ( basename( $url_path ) === 'admin.php' ) {
177
+ // get site options
178
+ $options = get_option( 'cookie_notice_options', $this->defaults['general'] );
179
+ }
180
+ } else {
181
+ if ( $this->is_plugin_network_active() && $this->network_options['global_override'] )
182
+ $options = $this->network_options;
183
+ else
184
+ $options = get_option( 'cookie_notice_options', $this->defaults['general'] );
185
+ }
186
+ }
187
+ } else
188
+ $options = get_option( 'cookie_notice_options', $this->defaults['general'] );
189
 
190
  // check legacy parameters
191
+ $options = $this->check_legacy_params( $options, [ 'refuse_opt', 'on_scroll', 'on_click', 'deactivation_delete', 'see_more' ] );
192
 
193
  // merge old options with new ones
194
+ $this->options['general'] = $this->multi_array_merge( $this->defaults['general'], $options );
 
 
195
 
196
  if ( ! isset( $this->options['general']['see_more_opt']['sync'] ) )
197
  $this->options['general']['see_more_opt']['sync'] = $this->defaults['general']['see_more_opt']['sync'];
 
 
 
 
 
 
 
 
 
 
198
 
199
+ // actions
200
+ add_action( 'plugins_loaded', [ $this, 'set_status' ] );
201
+ add_action( 'init', [ $this, 'register_shortcodes' ] );
202
+ add_action( 'init', [ $this, 'wpsc_add_cookie' ] );
203
+ add_action( 'init', [ $this, 'set_plugin_links' ] );
204
+ add_action( 'admin_init', [ $this, 'update_notice' ] );
205
+ add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
206
+ add_action( 'admin_footer', [ $this, 'deactivate_plugin_template' ] );
207
+ add_action( 'wp_ajax_cn_dismiss_notice', [ $this, 'ajax_dismiss_admin_notice' ] );
208
+ add_action( 'wp_ajax_cn-deactivate-plugin', [ $this, 'deactivate_plugin' ] );
209
  }
210
+
211
  /**
212
  * Set plugin status.
213
+ *
214
+ * @return void
215
  */
216
  public function set_status() {
217
+ if ( is_multisite() ) {
218
+ if ( $this->is_plugin_network_active() ) {
219
+ // network
220
+ if ( $this->is_network_admin() ) {
221
+ if ( $this->network_options['global_override'] )
222
+ $status = get_site_option( 'cookie_notice_status', '' );
223
+ else
224
+ $status = '';
225
+ // site
226
+ } else {
227
+ if ( $this->network_options['global_override'] )
228
+ $status = get_site_option( 'cookie_notice_status', '' );
229
+ else
230
+ $status = get_option( 'cookie_notice_status', '' );
231
+ }
232
+ } else {
233
+ // network
234
+ if ( $this->is_network_admin() )
235
+ $status = '';
236
+ // site
237
+ else
238
+ $status = get_option( 'cookie_notice_status', '' );
239
+ }
240
+ } else
241
+ $status = get_option( 'cookie_notice_status', '' );
242
+
243
+ // set status
244
+ $this->status = $this->check_status( $status );
245
+ }
246
+
247
+ /**
248
+ * Get plugin status.
249
+ *
250
+ * @return string
251
+ */
252
+ public function get_status() {
253
+ return $this->status;
254
+ }
255
+
256
+ /**
257
+ * Check plugin status.
258
+ *
259
+ * @param string $status
260
+ * @return string
261
+ */
262
+ public function check_status( $status ) {
263
+ return ! empty( $status ) && in_array( $status, [ 'active', 'pending' ], true ) ? $status : '';
264
+ }
265
+
266
+ /**
267
+ * Get endpoint URL.
268
+ *
269
+ * @param $type
270
+ * @param $query
271
+ * @return string
272
+ */
273
+ public function get_url( $type, $query = '' ) {
274
+ if ( $type === 'login' )
275
+ $url = $this->app_login_url;
276
+ elseif ( $type === 'dashboard' )
277
+ $url = $this->app_dashboard_url;
278
+ elseif ( $type === 'widget' )
279
+ $url = $this->app_widget_url;
280
+ elseif ( $type === 'host' )
281
+ $url = $this->app_host_url;
282
+ elseif ( $type === 'account_api' )
283
+ $url = $this->account_api_url;
284
+ elseif ( $type === 'designer_api' )
285
+ $url = $this->designer_api_url;
286
+ elseif ( $type === 'transactional_api' )
287
+ $url = $this->transactional_api_url;
288
+
289
+ return $url . ( $query !== '' ? $query : '' );
290
+ }
291
+
292
+ /**
293
+ * Get API key.
294
+ *
295
+ * @return string
296
+ */
297
+ public function get_api_key() {
298
+ return $this->x_api_key;
299
+ }
300
+
301
+ /**
302
+ * Check whether the current request is for the network administrative interface.
303
+ *
304
+ * @return bool
305
+ */
306
+ public function is_network_admin() {
307
+ return $this->network_admin;
308
+ }
309
+
310
+ /**
311
+ * Check whether the plugin is active for the entire network.
312
+ *
313
+ * @return bool
314
+ */
315
+ public function is_plugin_network_active() {
316
+ return $this->plugin_network_active;
317
+ }
318
+
319
+ /**
320
+ * Set network data.
321
+ *
322
+ * @return void
323
+ */
324
+ private function set_network_data() {
325
+ // load plugin.php file
326
+ if ( ! function_exists( 'is_plugin_active_for_network' ) )
327
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
328
+
329
+ // get plugin "dir/file" path
330
+ $this->plugin_basename = plugin_basename( __FILE__ );
331
+
332
+ // bypass is_network_admin() to handle AJAX requests properly.
333
+ $this->network_admin = is_multisite() && ( is_network_admin() || ( wp_doing_ajax() && isset( $_POST['cn_network'] ) && $_POST['cn_network'] === '1' ) );
334
+
335
+ // check whether the plugin is active for the entire network.
336
+ $this->plugin_network_active = is_plugin_active_for_network( $this->plugin_basename );
337
  }
338
 
339
  /**
342
  * @return void
343
  */
344
  private function includes() {
345
+ // get plugin path
346
+ $path = plugin_dir_path( __FILE__ );
347
+
348
+ include_once( $path . 'includes/bot-detect.php' );
349
+ include_once( $path . 'includes/dashboard.php' );
350
+ include_once( $path . 'includes/frontend.php' );
351
+ include_once( $path . 'includes/functions.php' );
352
+ include_once( $path . 'includes/settings.php' );
353
+ include_once( $path . 'includes/welcome.php' );
354
+ include_once( $path . 'includes/welcome-api.php' );
355
+ include_once( $path . 'includes/welcome-frontend.php' );
356
  }
357
+
358
  /**
359
  * Load textdomain.
360
+ *
361
+ * @return void
362
  */
363
  public function load_textdomain() {
364
+ load_plugin_textdomain( 'cookie-notice', false, dirname( $this->plugin_basename ) . '/languages/' );
365
  }
366
+
367
  /**
368
+ * Plugin activation.
369
+ *
370
+ * @global object $wpdb
371
+ *
372
+ * @param bool $networkwide
373
+ * @return void
374
  */
375
+ public function activation( $networkwide ) {
376
+ // network activation?
377
+ if ( $networkwide ) {
378
+ // add network options
379
+ add_site_option( 'cookie_notice_options', $this->defaults['general'] );
380
+ add_site_option( 'cookie_notice_status', '' );
381
+ add_site_option( 'cookie_notice_version', $this->defaults['version'] );
382
+
383
+ global $wpdb;
384
+
385
+ // get current site
386
+ $current_blog_id = $wpdb->blogid;
387
+
388
+ // get all available sites
389
+ $blogs_ids = $wpdb->get_col( 'SELECT blog_id FROM ' . $wpdb->blogs );
390
+
391
+ foreach ( $blogs_ids as $blog_id ) {
392
+ // change to another site
393
+ switch_to_blog( (int) $blog_id );
394
+
395
+ // run current site activation process
396
+ $this->activate_site();
397
+ }
398
+
399
+ // switch back to main site
400
+ switch_to_blog( $current_blog_id );
401
+ } else
402
+ $this->activate_site();
403
+ }
404
+
405
+ /**
406
+ * Single site activation.
407
+ *
408
+ * @return void
409
+ */
410
+ public function activate_site() {
411
+ // add default options
412
+ add_option( 'cookie_notice_options', $this->defaults['general'], '', false );
413
+ add_option( 'cookie_notice_status', '', '', false );
414
+ add_option( 'cookie_notice_version', $this->defaults['version'], '', false );
415
+ }
416
+
417
+ /**
418
+ * Plugin deactivation.
419
+ *
420
+ * @global object $wpdb
421
+ *
422
+ * @param bool $networkwide
423
+ * @return void
424
+ */
425
+ public function deactivation( $networkwide ) {
426
+ // network deactivation?
427
+ if ( $networkwide ) {
428
+ $delete = $this->options['general']['global_override'] && $this->options['general']['deactivation_delete'];
429
+
430
+ // delete network options?
431
+ if ( $delete ) {
432
+ delete_site_option( 'cookie_notice_options' );
433
+ delete_site_option( 'cookie_notice_status' );
434
+ delete_site_option( 'cookie_notice_app_analytics' );
435
+ delete_site_option( 'cookie_notice_version' );
436
+ }
437
+
438
+ global $wpdb;
439
+
440
+ // get current site
441
+ $current_blog_id = $wpdb->blogid;
442
+
443
+ // get all available sites
444
+ $blogs_ids = $wpdb->get_col( 'SELECT blog_id FROM ' . $wpdb->blogs );
445
+
446
+ foreach ( $blogs_ids as $blog_id ) {
447
+ // change to another site
448
+ switch_to_blog( (int) $blog_id );
449
+
450
+ // run current site deactivation process
451
+ $this->deactivate_site( $delete );
452
+ }
453
+
454
+ // switch back to main site
455
+ switch_to_blog( $current_blog_id );
456
+ } else
457
+ $this->deactivate_site();
458
  }
459
 
460
  /**
461
+ * Single site deactivation.
462
+ *
463
+ * @param boolean $force_deletion
464
+ * @return void
465
  */
466
+ public function deactivate_site( $force_deletion = false ) {
467
+ // delete settings?
468
+ if ( $force_deletion || $this->options['general']['deactivation_delete'] ) {
469
+ // delete options
470
  delete_option( 'cookie_notice_options' );
 
471
  delete_option( 'cookie_notice_status' );
472
  delete_option( 'cookie_notice_app_analytics' );
473
+ delete_option( 'cookie_notice_version' );
474
+
475
+ // delete transient
476
  delete_transient( 'cookie_notice_compliance_cache' );
477
  }
478
+
479
+ // remove wp super cache cookie
480
  $this->wpsc_delete_cookie();
481
  }
482
 
483
+ /**
484
+ * Retrieve the timezone of the site as a string.
485
+ *
486
+ * @return string
487
+ */
488
+ public function timezone_string() {
489
+ if ( function_exists( 'wp_timezone_string' ) )
490
+ return wp_timezone_string();
491
+
492
+ $timezone_string = get_option( 'timezone_string' );
493
+
494
+ if ( $timezone_string )
495
+ return $timezone_string;
496
+
497
+ $offset = (float) get_option( 'gmt_offset' );
498
+ $hours = (int) $offset;
499
+ $minutes = ( $offset - $hours );
500
+ $sign = ( $offset < 0 ) ? '-' : '+';
501
+ $abs_hour = abs( $hours );
502
+ $abs_mins = abs( $minutes * 60 );
503
+ $tz_offset = sprintf( '%s%02d:%02d', $sign, $abs_hour, $abs_mins );
504
+
505
+ return $tz_offset;
506
+ }
507
+
508
  /**
509
  * Update notice.
510
+ *
511
  * @return void
512
  */
513
  public function update_notice() {
514
  if ( ! current_user_can( 'install_plugins' ) )
515
  return;
516
+
517
  // bail an ajax
518
+ if ( wp_doing_ajax() )
519
  return;
520
+
521
+ $network = $this->is_network_admin();
522
+
523
+ $current_update = 7;
524
+
525
  // get current database version
526
+ if ( $network )
527
+ $current_db_version = get_site_option( 'cookie_notice_version', '1.0.0' );
528
+ else
529
+ $current_db_version = get_option( 'cookie_notice_version', '1.0.0' );
530
+
531
  if ( version_compare( $current_db_version, $this->defaults['version'], '<' ) && $this->options['general']['update_version'] < $current_update ) {
532
  // check version, if update version is lower than plugin version, set update notice to true
533
+ $this->options['general']['update_version'] = $current_update;
534
+ $this->options['general']['update_notice'] = true;
535
 
536
+ if ( $network ) {
537
+ $this->options['general']['update_notice_diss'] = false;
538
+
539
+ // update options
540
+ update_site_option( 'cookie_notice_options', $this->options['general'] );
541
+
542
+ // update plugin version
543
+ update_site_option( 'cookie_notice_version', $this->defaults['version'] );
544
+ } else {
545
+ // update options
546
+ update_option( 'cookie_notice_options', $this->options['general'] );
547
+
548
+ // update plugin version
549
+ update_option( 'cookie_notice_version', $this->defaults['version'], false );
550
+ }
551
  }
552
+
553
  // if visiting settings, mark notice as read
554
  if ( ! empty( $_GET['page'] ) && $_GET['page'] === 'cookie-notice' && ! empty( $_GET['welcome'] ) ) {
555
+ $this->options['general']['update_notice'] = false;
556
+
557
+ if ( $network ) {
558
+ $this->options['general']['update_notice_diss'] = true;
559
+
560
+ update_site_option( 'cookie_notice_options', $this->options['general'] );
561
+ } else
562
+ update_option( 'cookie_notice_options', $this->options['general'] );
563
  }
564
+
565
+ if ( is_multisite() && ( ( $this->is_plugin_network_active() && ! $network && $this->network_options['global_override'] ) || ( $network && ! $this->is_plugin_network_active() ) ) )
566
+ $this->options['general']['update_notice'] = false;
567
+
568
+ // get cookie compliance status
569
+ $status = $this->get_status();
570
+
571
  // show notice, if no compliance only
572
+ if ( $this->options['general']['update_notice'] === true && empty( $status ) ) {
573
+ $this->add_notice( '<div class="cn-notice-text"><h2>' . __( 'German Court Fines Website Owner for Using Google-Hosted Fonts', 'cookie-notice' ) . '</h2><p>' . __( 'The German Court ruled that use of Google Fonts without prior consent is a violation of Europe’s GDPR (General Data Protection Regulation) because Google Fonts exposes the visitor’s IP address. Court’s ruling threatens a fine of €250,000 for each case of infringement if the site owner does not comply. If your website uses Google Fonts, click "Run Compliance Check" to make sure your website complies with the latest consent capture and cookie blocking requirements.', 'cookie-notice' ) . '</p><p class="cn-notice-actions"><a href="' . ( $network ? network_admin_url( 'admin.php?page=cookie-notice&welcome=1' ) : admin_url( 'admin.php?page=cookie-notice&welcome=1' ) ) . '" class="button button-primary cn-button">' . __( 'Run Compliance Check', 'cookie-notice' ) . '</a> <a href="#" class="button-link cn-notice-dismiss">' . __( 'Dismiss Notice', 'cookie-notice' ) . '</a></p></div>', 'error', 'div' );
 
574
  }
575
+
576
  // show treshold limit warning, compliance only
577
+ if ( $status === 'active' ) {
578
  // get analytics data options
579
+ if ( $network )
580
+ $analytics = get_site_option( 'cookie_notice_app_analytics', [] );
581
+ else
582
+ $analytics = get_option( 'cookie_notice_app_analytics', [] );
583
+
584
+ if ( is_multisite() && ( ( $network && ! $this->is_plugin_network_active() && ! $this->network_options['global_override'] ) || ( ! $network && $this->is_plugin_network_active() && $this->network_options['global_override'] ) ) )
585
+ $allow_notice = false;
586
+ else
587
+ $allow_notice = true;
588
+
589
+ if ( ! empty( $analytics ) && $allow_notice ) {
590
  // cycle usage data
591
+ $cycle_usage = [
592
+ 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
593
+ 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0,
594
+ 'end_date' => ! empty( $analytics['cycleUsage']->endDate ) ? date_create_from_format( '!Y-m-d', $analytics['cycleUsage']->endDate ) : date_create_from_format( 'Y-m-d H:i:s', current_time( 'mysql', true ) ),
595
+ 'last_updated' => ! empty( $analytics['lastUpdated'] ) ? date_create_from_format( 'Y-m-d H:i:s', $analytics['lastUpdated'] ) : date_create_from_format( 'Y-m-d H:i:s', current_time( 'mysql', true ) )
596
+ ];
597
+
 
 
598
  // if threshold in use
599
  if ( $cycle_usage['threshold'] ) {
600
  // if threshold exceeded and there was no notice before
601
+ if ( $cycle_usage['visits'] >= $cycle_usage['threshold'] && $cycle_usage['last_updated']->getTimestamp() < $cycle_usage['end_date']->getTimestamp() && $this->options['general']['update_threshold_date'] < $cycle_usage['end_date']->getTimestamp() ) {
602
  $date_format = get_option( 'date_format' );
603
+
604
+ $upgrade_link = $this->get_url( 'dashboard', '?app-id=' . $this->options['general']['app_id'] . '&open-modal=payment' );
605
  $threshold = $cycle_usage['threshold'];
606
+ $cycle_date = date_i18n( $date_format, $cycle_usage['end_date']->getTimestamp() );
607
+
608
+ $this->add_notice( '<div class="cn-notice-text" data-delay="' . $cycle_usage['end_date']->getTimestamp() . '"><h2>' . __( 'Cookie Compliance Warning', 'cookie-notice') . '</h2><p>' . sprintf( __( 'Your website has reached the <b>%1$s visits usage limit for the Cookie Compliance Free Plan</b>. Compliance services such as Consent Record Storage, Autoblocking, and Consent Analytics have been deactivated until current usage cycle ends on %2$s.', 'cookie-notice' ), $threshold, $cycle_date ) . '<br>' . sprintf( __( 'To reactivate compliance services now, <a href="%s" target="_blank">upgrade your domain to a Pro plan.</a>', 'cookie-notice' ) . '</p></div>', $upgrade_link ), 'cn-threshold error is-dismissible', 'div' );
609
  }
610
  }
611
  }
613
  }
614
 
615
  /**
616
+ * Add admin notice.
617
+ *
618
  * @param string $html
619
  * @param string $status
620
+ * @param string $container
621
+ * @return void
622
  */
623
  private function add_notice( $html = '', $status = 'error', $container = '' ) {
624
+ $this->notices[] = [
625
+ 'html' => $html,
626
+ 'status' => $status,
627
+ 'container' => ( ! empty( $container ) && in_array( $container, [ 'p', 'div' ] ) ? $container : '' )
628
+ ];
629
+
630
+ add_action( 'admin_notices', [ $this, 'display_notice' ], 0 );
631
+ add_action( 'network_admin_notices', [ $this, 'display_notice' ], 0 );
632
  }
633
 
634
  /**
635
  * Print admin notices.
636
+ *
637
+ * @return void
638
  */
639
  public function display_notice() {
640
  foreach( $this->notices as $notice ) {
649
 
650
  /**
651
  * Dismiss admin notice.
652
+ *
653
+ * @return void
654
  */
655
  public function ajax_dismiss_admin_notice() {
656
  if ( ! current_user_can( 'install_plugins' ) )
658
 
659
  if ( wp_verify_nonce( $_REQUEST['nonce'], 'cn_dismiss_notice' ) ) {
660
  $notice_action = empty( $_REQUEST['notice_action'] ) || $_REQUEST['notice_action'] === 'dismiss' ? 'dismiss' : sanitize_text_field( $_REQUEST['notice_action'] );
661
+ $network = is_multisite() && isset( $_POST['cn_network'] ) && $_POST['cn_network'] === '1';
662
 
663
  switch ( $notice_action ) {
664
+ // threshold notice
665
  case 'threshold':
666
  // set delay period last cycle day
667
  $delay = isset( $_REQUEST['param'] ) ? (int) $_REQUEST['param'] : 0;
668
+
669
+ $this->options['general']['update_threshold_date'] = $delay + DAY_IN_SECONDS;
670
+
671
+ // update options
672
+ if ( $network )
673
+ update_site_option( 'cookie_notice_options', $this->options['general'] );
674
+ else
675
+ update_option( 'cookie_notice_options', $this->options['general'] );
676
  break;
677
+
678
  // delay notice
679
  case 'delay':
680
  // set delay period to 1 week from now
681
+ $this->options['general']['update_delay_date'] = time() + 1209600;
682
+
 
 
 
 
 
 
 
683
  // update options
684
+ if ( $network )
685
+ update_site_option( 'cookie_notice_options', $this->options['general'] );
686
+ else
687
+ update_option( 'cookie_notice_options', $this->options['general'] );
688
  break;
689
 
690
  // hide notice
691
+ case 'approve':
692
  default:
693
+ $this->options['general']['update_notice'] = false;
694
+ $this->options['general']['update_delay_date'] = 0;
695
 
696
+ // update options
697
+ if ( $network ) {
698
+ $this->options['general']['update_notice_diss'] = true;
699
+
700
+ update_site_option( 'cookie_notice_options', $this->options['general'] );
701
+ } else
702
+ update_option( 'cookie_notice_options', $this->options['general'] );
703
  }
704
  }
705
 
712
  * @return void
713
  */
714
  public function register_shortcodes() {
715
+ add_shortcode( 'cookies_accepted', [ $this, 'cookies_accepted_shortcode' ] );
716
+ add_shortcode( 'cookies_revoke', [ $this, 'cookies_revoke_shortcode' ] );
717
+ add_shortcode( 'cookies_policy_link', [ $this, 'cookies_policy_link_shortcode' ] );
718
  }
719
 
720
  /**
722
  *
723
  * @param array $args
724
  * @param mixed $content
725
+ * @return string
726
  */
727
  public function cookies_accepted_shortcode( $args, $content ) {
728
  if ( $this->cookies_accepted() ) {
740
  }
741
 
742
  /**
743
+ * Register cookies revoke shortcode.
744
  *
745
  * @param array $args
746
  * @param mixed $content
747
+ * @return string
748
  */
749
  public function cookies_revoke_shortcode( $args, $content ) {
750
  // get options
751
  $options = $this->options['general'];
752
 
753
+ // WPML >= 3.2
754
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) )
755
+ $options['revoke_text'] = apply_filters( 'wpml_translate_single_string', $options['revoke_text'], 'Cookie Notice', 'Revoke button text' );
756
+ // WPML and Polylang compatibility
757
+ elseif ( function_exists( 'icl_t' ) )
758
+ $options['revoke_text'] = icl_t( 'Cookie Notice', 'Revoke button text', $options['revoke_text'] );
759
+
760
  // defaults
761
+ $defaults = [
762
  'title' => $options['revoke_text'],
763
  'class' => $options['css_class']
764
+ ];
765
 
766
  // combine shortcode arguments
767
  $args = shortcode_atts( $defaults, $args );
770
  $args['class'] = esc_attr( $args['class'] );
771
 
772
  if ( Cookie_Notice()->get_status() === 'active' )
773
+ $shortcode = '<a href="#" class="cn-revoke-cookie cn-button-inline cn-revoke-inline' . ( $args['class'] !== '' ? ' ' . $args['class'] : '' ) . '" title="' . esc_attr( $args['title'] ) . '" data-hu-action="cookies-notice-revoke">' . esc_html( $args['title'] ) . '</a>';
774
  else
775
+ $shortcode = '<a href="#" class="cn-revoke-cookie cn-button-inline cn-revoke-inline' . ( $args['class'] !== '' ? ' ' . $args['class'] : '' ) . '" title="' . esc_attr( $args['title'] ) . '">' . esc_html( $args['title'] ) . '</a>';
776
 
777
  return $shortcode;
778
  }
788
  // get options
789
  $options = $this->options['general'];
790
 
791
+ // WPML >= 3.2
792
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
793
+ $options['see_more_opt']['text'] = apply_filters( 'wpml_translate_single_string', $options['see_more_opt']['text'], 'Cookie Notice', 'Privacy policy text' );
794
+ $options['see_more_opt']['link'] = apply_filters( 'wpml_translate_single_string', $options['see_more_opt']['link'], 'Cookie Notice', 'Custom link' );
795
+ // WPML and Polylang compatibility
796
+ } elseif ( function_exists( 'icl_t' ) ) {
797
+ $options['see_more_opt']['text'] = icl_t( 'Cookie Notice', 'Privacy policy text', $options['see_more_opt']['text'] );
798
+ $options['see_more_opt']['link'] = icl_t( 'Cookie Notice', 'Custom link', $options['see_more_opt']['link'] );
799
+ }
800
+
801
+ if ( $options['see_more_opt']['link_type'] === 'page' ) {
802
+ // multisite with global override?
803
+ if ( is_multisite() && $this->is_plugin_network_active() && $this->network_options['global_override'] ) {
804
+ // get main site id
805
+ $main_site_id = get_main_site_id();
806
+
807
+ // switch to main site
808
+ switch_to_blog( $main_site_id );
809
+
810
+ // update page id for current language if needed
811
+ if ( function_exists( 'icl_object_id' ) )
812
+ $options['see_more_opt']['id'] = icl_object_id( $options['see_more_opt']['id'], 'page', true );
813
+
814
+ // get main site privacy policy link
815
+ $permalink = get_permalink( $options['see_more_opt']['id'] );
816
+
817
+ // restore current site
818
+ restore_current_blog();
819
+ } else {
820
+ // update page id for current language if needed
821
+ if ( function_exists( 'icl_object_id' ) )
822
+ $options['see_more_opt']['id'] = icl_object_id( $options['see_more_opt']['id'], 'page', true );
823
+
824
+ // get privacy policy link
825
+ $permalink = get_permalink( $options['see_more_opt']['id'] );
826
+ }
827
+ }
828
+
829
  // defaults
830
+ $defaults = [
831
  'title' => esc_html( $options['see_more_opt']['text'] !== '' ? $options['see_more_opt']['text'] : '&#x279c;' ),
832
+ 'link' => ( $options['see_more_opt']['link_type'] === 'custom' ? esc_url( $options['see_more_opt']['link'] ) : esc_url( $permalink ) ),
833
  'class' => esc_attr( $options['css_class'] )
834
+ ];
835
 
836
  // combine shortcode arguments
837
  $args = shortcode_atts( $defaults, $args );
843
 
844
  /**
845
  * Check if cookies are accepted.
846
+ *
847
  * @return bool
848
  */
849
  public static function cookies_accepted() {
850
  if ( Cookie_Notice()->get_status() === 'active' ) {
851
+ $cookies = isset( $_COOKIE['hu-consent'] ) ? json_decode( stripslashes( $_COOKIE['hu-consent'] ), true ) : [];
852
+
853
  if ( ! empty( $cookies ) && is_array( $cookies ) ) {
854
  foreach( $cookies as $cookie_name => $cookie_value ) {
855
  switch ( $cookie_name ) {
856
  case 'consent':
857
  $cookies[$cookie_name] = (bool) $cookie_value;
858
  break;
859
+
860
  default:
861
  $cookies[$cookie_name] = is_array( $cookie_value ) ? array_map( 'sanitize_text_field', $cookie_value ) : sanitize_text_field( $cookie_value );
862
  }
863
  }
864
  }
865
 
866
+ $result = ( is_array( $cookies ) && json_last_error() === JSON_ERROR_NONE && ! empty( $cookies['consent'] ) );
867
  } else
868
  $result = isset( $_COOKIE['cookie_notice_accepted'] ) && $_COOKIE['cookie_notice_accepted'] === 'true';
869
 
873
  /**
874
  * Check if cookies are set.
875
  *
876
+ * @return boolean
877
  */
878
  public function cookies_set() {
879
  if ( Cookie_Notice()->get_status() === 'active' )
886
 
887
  /**
888
  * Add WP Super Cache cookie.
889
+ *
890
+ * @return void
891
  */
892
  public function wpsc_add_cookie() {
893
  if ( Cookie_Notice()->get_status() === 'active' )
898
 
899
  /**
900
  * Delete WP Super Cache cookie.
901
+ *
902
+ * @return void
903
  */
904
  public function wpsc_delete_cookie() {
905
  if ( Cookie_Notice()->get_status() === 'active' )
907
  else
908
  do_action( 'wpsc_delete_cookie', 'cookie_notice_accepted' );
909
  }
910
+
911
  /**
912
  * Enqueue admin scripts and styles.
913
  *
919
  if ( $page === 'plugins.php' ) {
920
  add_thickbox();
921
 
922
+ wp_enqueue_script( 'cookie-notice-admin-plugins', plugins_url( '/js/admin-plugins.js', __FILE__ ), [ 'jquery' ], $this->defaults['version'] );
923
 
924
+ wp_enqueue_style( 'cookie-notice-admin-plugins', plugins_url( '/css/admin-plugins.css', __FILE__ ), [], $this->defaults['version'] );
925
 
926
  wp_localize_script(
927
  'cookie-notice-admin-plugins',
928
  'cnArgsPlugins',
929
+ [
930
  'deactivate' => __( 'Cookie Notice & Compliance - Deactivation survey', 'cookie-notice' ),
931
  'nonce' => wp_create_nonce( 'cn-deactivate-plugin' )
932
+ ]
933
  );
934
  }
935
+
936
  // notice js and css
937
  wp_enqueue_script(
938
+ 'cookie-notice-admin-notice', plugins_url( '/js/admin-notice.js', __FILE__ ), [ 'jquery' ], Cookie_Notice()->defaults['version']
939
  );
940
 
941
  wp_localize_script(
942
+ 'cookie-notice-admin-notice',
943
+ 'cnArgsNotice',
944
+ [
945
+ 'ajaxURL' => admin_url( 'admin-ajax.php' ),
946
+ 'nonce' => wp_create_nonce( 'cn_dismiss_notice' ),
947
+ 'network' => (int) $this->is_network_admin()
948
+ ]
949
  );
950
 
951
  wp_enqueue_style(
952
+ 'cookie-notice-admin-notice', plugins_url( '/css/admin-notice.css', __FILE__ ), [], Cookie_Notice()->defaults['version']
953
  );
954
  }
955
 
956
+ /**
957
+ * Set plugin links.
958
+ *
959
+ * @return void
960
+ */
961
+ public function set_plugin_links() {
962
+ // filters
963
+ add_filter( 'plugin_action_links', [ $this, 'plugin_action_links' ], 10, 2 );
964
+ add_filter( 'network_admin_plugin_action_links', [ $this, 'plugin_action_links' ], 10, 2 );
965
+ }
966
+
967
  /**
968
  * Add links to settings page.
969
+ *
970
  * @param array $links
971
  * @param string $file
972
  * @return array
974
  public function plugin_action_links( $links, $file ) {
975
  if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
976
  return $links;
 
 
977
 
978
+ if ( $file === $this->plugin_basename ) {
 
 
979
  if ( ! empty( $links['deactivate'] ) ) {
980
  // link already contains class attribute?
981
  if ( preg_match( '/<a.*?class=(\'|")(.*?)(\'|").*?>/is', $links['deactivate'], $result ) === 1 )
990
  }
991
  }
992
 
993
+ // skip settings link if plugin is activated from main site
994
+ if ( ! ( $this->is_network_admin() && ! $this->is_plugin_network_active() ) ) {
995
+ // put settings link at start
996
+ array_unshift( $links, sprintf( '<a href="%s">%s</a>', $this->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice' ) : admin_url( 'admin.php?page=cookie-notice' ), __( 'Settings', 'cookie-notice' ) ) );
997
+ }
998
 
999
+ // get cookie compliance status
1000
+ $status = $this->get_status();
1001
+
1002
+ if ( is_multisite() ) {
1003
+ $check_status = empty( $status ) && ( ( $this->is_network_admin() && $this->is_plugin_network_active() && $this->network_options['global_override'] ) || ( ! $this->is_network_admin() && ( ( $this->is_plugin_network_active() && ! $this->network_options['global_override'] ) || ! $this->is_plugin_network_active() ) ) );
1004
+ } else
1005
+ $check_status = empty( $status );
1006
+
1007
+ // add upgrade link
1008
+ if ( $check_status )
1009
+ $links[] = sprintf( '<a href="%s" style="color: #20C19E; font-weight: bold;">%s</a>', $this->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice&welcome=1' ) : admin_url( 'admin.php?page=cookie-notice&welcome=1' ), __( 'Free Upgrade', 'cookie-notice' ) );
1010
  }
1011
 
1012
  return $links;
1013
  }
1014
+
1015
  /**
1016
  * Deactivation modal HTML template.
1017
  *
1018
+ * @global string $pagenow
1019
+ *
1020
  * @return void
1021
  */
1022
  public function deactivate_plugin_template() {
1034
  <p><em>' . __( "We're sorry to see you go. Could you please tell us what happened?", 'cookie-notice' ) . '</em></p>
1035
  <ul>';
1036
 
1037
+ foreach ( [
1038
  '1' => __( "I couldn't figure out how to make it work.", 'cookie-notice' ),
1039
  '2' => __( 'I found another plugin to use for the same task.', 'cookie-notice' ),
1040
  '3' => __( 'The Cookie Compliance banner is too big.', 'cookie-notice' ),
1043
  '6' => __( 'The web application user interface is not clear to me.', 'cookie-notice' ),
1044
  '7' => __( "Support isn't timely.", 'cookie-notice' ),
1045
  '8' => __( 'Other', 'cookie-notice' )
1046
+ ] as $option => $text ) {
1047
+ echo '
1048
  <li><label><input type="radio" name="cn_deactivation_option" value="' . $option . '" ' . checked( '8', $option, false ) . ' />' . esc_html( $text ) . '</label></li>';
1049
  }
1050
 
1051
+ echo '
1052
  </ul>
1053
  </div>
1054
  <div class="cn-deactivation-textarea">
1078
  if ( isset( $_POST['option_id'] ) ) {
1079
  $option_id = (int) $_POST['option_id'];
1080
  $other = esc_html( $_POST['other'] );
1081
+
1082
  // avoid fake submissions
1083
  if ( $option_id == 8 && $other == '' )
1084
  wp_send_json_success();
1085
 
1086
  wp_remote_post(
1087
+ 'https://hu-manity.co/wp-json/api/v1/forms/',
1088
+ [
1089
+ 'timeout' => 15,
1090
+ 'blocking' => true,
1091
+ 'headers' => [],
1092
+ 'body' => [
1093
+ 'id' => 1,
1094
+ 'option' => $option_id,
1095
+ 'other' => $other,
1096
+ 'referrer' => get_site_url()
1097
+ ]
1098
+ ]
1099
  );
1100
 
1101
  wp_send_json_success();
1114
  'cn_refuse_code_allowed_html',
1115
  array_merge(
1116
  wp_kses_allowed_html( 'post' ),
1117
+ [
1118
+ 'script' => [
1119
+ 'type' => [],
1120
+ 'src' => [],
1121
+ 'charset' => [],
1122
+ 'async' => []
1123
+ ],
1124
+ 'noscript' => [],
1125
+ 'style' => [
1126
+ 'type' => []
1127
+ ],
1128
+ 'iframe' => [
1129
+ 'src' => [],
1130
+ 'height' => [],
1131
+ 'width' => [],
1132
+ 'frameborder' => [],
1133
+ 'allowfullscreen' => []
1134
+ ]
1135
+ ]
1136
  )
1137
  );
1138
  }
1139
 
1140
  /**
1141
  * Helper: convert hex color to rgb color.
1142
+ *
1143
  * @param type $color
1144
+ * @return bool|array
1145
  */
1146
  public function hex2rgb( $color ) {
1147
  if ( $color[0] == '#' )
1148
  $color = substr( $color, 1 );
1149
 
1150
  if ( strlen( $color ) == 6 )
1151
+ list( $r, $g, $b ) = [ $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] ];
1152
  elseif ( strlen( $color ) == 3 )
1153
+ list( $r, $g, $b ) = [ $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] ];
1154
  else
1155
  return false;
1156
 
1158
  $g = hexdec( $g );
1159
  $b = hexdec( $b );
1160
 
1161
+ return [ $r, $g, $b ];
1162
  }
1163
+
1164
  /**
1165
+ * Helper: Convert undersocores to CamelCase.
1166
+ *
1167
+ * @param string $string
1168
  * @param bool $capitalize_first_char
1169
  * @return string
1170
  */
1177
 
1178
  return $str;
1179
  }
1180
+
1181
  /**
1182
  * Check legacy parameters that were yes/no strings.
1183
  *
1203
  * $siblings examples: array( '=>', 'only_first_level', 'first_level=>second_level', 'first_key=>next_key=>sibling' ) and so on.
1204
  * Single '=>' means that all siblings of the highest level will be kept in the final array.
1205
  *
1206
+ * @param array $defaults Array with defaults values
1207
  * @param array $array Array to merge
1208
  * @param boolean|array $siblings Whether to allow "string" siblings to copy from $array if they do not exist in $defaults, false otherwise
1209
+ * @return array
1210
  */
1211
  public function multi_array_merge( $defaults, $array, $siblings = false ) {
1212
  // make a copy for better performance and to prevent $default override in foreach
1213
  $copy = $defaults;
1214
 
1215
  // prepare siblings for recursive deeper level
1216
+ $new_siblings = [];
1217
 
1218
  // allow siblings?
1219
  if ( ! empty( $siblings ) && is_array( $siblings ) ) {
1239
 
1240
  // more than one sibling child?
1241
  if ( count( $ex ) > 1 )
1242
+ $new_siblings[$ex[0]] = [ substr_replace( $sibling, '', 0, strlen( $ex[0] . '=>' ) ) ];
1243
  // no more sibling children
1244
  else
1245
  $new_siblings[$ex[0]] = false;
1271
 
1272
  return $copy;
1273
  }
 
 
 
 
 
 
 
 
 
1274
 
1275
  /**
1276
+ * Indicate if current page is the Cookie Policy page.
1277
  *
1278
  * @return bool
1279
  */
1280
  public function is_cookie_policy_page() {
1281
  $see_more = $this->options['general']['see_more_opt'];
1282
+
1283
  if ( $see_more['link_type'] !== 'page' )
1284
  return false;
1285
 
1290
 
1291
  return $current_page->post_name === $cp_slug;
1292
  }
 
1293
  }
1294
 
1295
  /**
1305
  return $instance;
1306
  }
1307
 
1308
+ $cookie_notice = Cookie_Notice();
css/admin-notice.css CHANGED
@@ -1,52 +1,43 @@
1
- #cn-admin-notice.cn-notice {
2
- border-left-color: #20c19e;
3
- }
4
-
5
- .cn-notice .cn-notice-container {
6
- padding: 1em;
7
- display: flex;
8
- justify-content: space-between;
9
- align-items: center;
10
- }
11
-
12
- .cn-notice .cn-notice-actions {
13
- margin-bottom: 0;
14
- }
15
-
16
- .cn-notice .cn-notice-actions .button {
17
- display: inline-block;
18
- margin: 0.5em 0 0;
19
- }
20
-
21
- .cn-notice .cn-notice-text h2 {
22
- margin-top: 0;
23
- margin-bottom: 0.5em;
24
- }
25
-
26
- .cn-notice .cn-notice-dismiss {
27
- margin-left: 1em;
28
- }
29
-
30
- .cn-notice .cn-notice-text strong {
31
- color: #000;
32
- }
33
-
34
- .cn-notice .cn-notice-text p:last-child {
35
- margin-bottom: 0;
36
- }
37
-
38
- .cn-notice .cn-notice-icon svg path {
39
- fill: #666 !important;
40
- }
41
-
42
- @media only screen and (max-width: 960px) {
43
- .cn-notice .cn-notice-container {
44
- flex-direction: column;
45
- align-items: initial;
46
- }
47
-
48
- .cn-notice .cn-notice-container .cn-notice-text {
49
- order: 1;
50
- padding-top: 1em;
51
- }
52
  }
1
+ #cn-admin-notice.cn-notice {
2
+ border-left-color: #20c19e;
3
+ }
4
+ .cn-notice .cn-notice-container {
5
+ padding: 1em;
6
+ display: flex;
7
+ justify-content: space-between;
8
+ align-items: center;
9
+ }
10
+ .cn-notice .cn-notice-actions {
11
+ margin-bottom: 0;
12
+ }
13
+ .cn-notice .cn-notice-actions .button {
14
+ display: inline-block;
15
+ margin: 0.5em 0 0;
16
+ }
17
+ .cn-notice .cn-notice-text h2 {
18
+ margin-top: 0;
19
+ margin-bottom: 0.5em;
20
+ }
21
+ .cn-notice .cn-notice-dismiss {
22
+ margin-left: 1em;
23
+ }
24
+ .cn-notice .cn-notice-text strong {
25
+ color: #000;
26
+ }
27
+ .cn-notice .cn-notice-text p:last-child {
28
+ margin-bottom: 0;
29
+ }
30
+ .cn-notice .cn-notice-icon svg path {
31
+ fill: #666 !important;
32
+ }
33
+ @media only screen and (max-width: 960px) {
34
+ .cn-notice .cn-notice-container {
35
+ flex-direction: column;
36
+ align-items: initial;
37
+ }
38
+
39
+ .cn-notice .cn-notice-container .cn-notice-text {
40
+ order: 1;
41
+ padding-top: 1em;
42
+ }
 
 
 
 
 
 
 
 
 
43
  }
css/admin-plugins.css CHANGED
@@ -1,45 +1,44 @@
1
- .cn-deactivation-modal {
2
- max-height: 500px;
3
- overflow: hidden;
4
- top: 50% !important;
5
- transform: translateY(-50%);
6
- }
7
- .cn-deactivation-modal #TB_title {
8
- padding: 13px 16px;
9
- background: #f3f3f3;
10
- }
11
- .cn-deactivation-modal #TB_title > div {
12
- padding: 0;
13
- color: #000;
14
- }
15
- .cn-deactivation-modal #TB_ajaxContent {
16
- width: auto !important;
17
- height: calc(100% - 112px) !important;
18
- padding: 0;
19
- }
20
- .cn-deactivation-options p:first-child {
21
- margin-top: 0;
22
- }
23
- .cn-deactivation-buttons .spinner {
24
- float: none;
25
- /* text-align: right; */
26
- }
27
- #cn-deactivation-container {
28
- width: 100%;
29
- }
30
- #cn-deactivation-container textarea {
31
- width: 100%;
32
- min-height: 100px;
33
- }
34
- #cn-deactivation-body {
35
- padding: 13px 16px;
36
- }
37
- #cn-deactivation-footer {
38
- padding: 13px 16px;
39
- position: absolute;
40
- right: 0;
41
- bottom: 0;
42
- left: 0;
43
- border-top: 1px solid #ddd;
44
- background: #f3f3f3;
45
  }
1
+ .cn-deactivation-modal {
2
+ max-height: 500px;
3
+ overflow: hidden;
4
+ top: 50% !important;
5
+ transform: translateY(-50%);
6
+ }
7
+ .cn-deactivation-modal #TB_title {
8
+ padding: 13px 16px;
9
+ background: #f3f3f3;
10
+ }
11
+ .cn-deactivation-modal #TB_title > div {
12
+ padding: 0;
13
+ color: #000;
14
+ }
15
+ .cn-deactivation-modal #TB_ajaxContent {
16
+ width: auto !important;
17
+ height: calc(100% - 112px) !important;
18
+ padding: 0;
19
+ }
20
+ .cn-deactivation-options p:first-child {
21
+ margin-top: 0;
22
+ }
23
+ #cn-deactivation-container {
24
+ width: 100%;
25
+ }
26
+ #cn-deactivation-container textarea {
27
+ width: 100%;
28
+ min-height: 100px;
29
+ }
30
+ #cn-deactivation-body {
31
+ padding: 13px 16px;
32
+ }
33
+ #cn-deactivation-footer {
34
+ padding: 13px 16px;
35
+ position: absolute;
36
+ right: 0;
37
+ bottom: 0;
38
+ left: 0;
39
+ border-top: 1px solid #ddd;
40
+ background: #f3f3f3;
41
+ }
42
+ #cn-deactivation-footer .spinner {
43
+ float: none;
 
44
  }
css/admin.css CHANGED
@@ -1,137 +1,143 @@
1
- .cookie-notice-sidebar{
2
  float:right;
3
  width:280px;
4
  margin:20px -300px 20px 20px;
5
  position:relative
6
  }
7
- .cookie-notice-sidebar .inner{
8
  padding:1.33em
9
  }
10
- .cookie-notice-sidebar>div:not(:last-child){
11
  margin-bottom:3em
12
  }
13
- .cookie-notice-sidebar .inner img{
14
  max-width:80%;
15
  height:auto;
16
  display:block;
17
  margin:20px auto
18
  }
19
- .cookie-notice-credits{
20
  background:#fff;
21
  box-shadow:0 0 0 1px rgba(0,0,0,.05)
22
  }
23
- .cookie-notice-credits .inner{
24
  text-align:center;
25
  margin:0
26
  }
27
- .button.cn-button{
28
  background-color:#20c19e;
29
  border-color:#20c19e
30
  }
31
- .button.cn-button:active,.button.cn-button:focus,.button.cn-button:hover{
32
  background-color:#1ca98a;
33
  border-color:#1ca98a
34
  }
35
- .button.cn-button:focus{
36
  box-shadow:0 0 0 1px #fff,0 0 0 3px #20c19e
37
  }
38
- .cookie-notice-settings .cookie-notice-credits h2{
39
  border:none;
40
  padding-bottom:0
41
  }
42
- .cookie-notice-credits h3{
43
  font-size:14px;
44
  line-height:1.4;
45
  margin:0;
46
  padding:.66em 1.33em;
47
  border-bottom:1px solid #eee
48
  }
49
- .cookie-notice-settings .df-credits form{
50
  min-width:260px;
51
  margin-bottom:1em
52
  }
53
- .cookie-notice-settings .df-credits form input{
54
  margin:0;
55
  padding:0
56
  }
57
- .cookie-notice-settings{
58
  margin-right:300px
59
  }
60
- .cookie-notice-settings hr,.df-credits hr{
61
  border:solid #eee;
62
  border-width:1px 0 0;
63
  clear:both;
64
  height:0
65
  }
66
- .cookie-notice-settings form{
67
  float:left;
68
  min-width:463px;
69
  width:100%
70
  }
71
- .cookie-notice-settings form h2{
 
 
 
 
 
 
72
  margin:1.5em 0;
73
  padding-bottom:1em;
74
  border-bottom:1px solid #ccc
75
  }
76
- .cookie-notice-settings .ui-button{
77
  margin-bottom:5px
78
  }
79
- .cookie-notice-settings .description{
80
  font-size:13px;
81
  margin-bottom:8px
82
  }
83
- .cookie-notice-settings .description strong{
84
  color:#444
85
  }
86
- #cn_colors label{
87
  min-width:10em;
88
  display:inline-block
89
  }
90
- #cn_colors div{
91
  vertical-align:middle
92
  }
93
- #cn_refuse_code .nav-tab-wrapper{
94
  padding-top:0
95
  }
96
- #cn_refuse_code .refuse-code-tab{
97
  display:none
98
  }
99
- #cn_refuse_code .refuse-code-tab.active{
100
  display:block
101
  }
102
- #cn_refuse_code .refuse-code-tab .description{
103
  margin-top:10px
104
  }
105
- .cn_compliance_status{
106
  margin-right:15px
107
  }
108
- #cn_app_status .cn_compliance_status label{
109
  margin-left:5px!important
110
  }
111
- #cn_app_status{
112
  margin-bottom:30px
113
  }
114
- #cn_app_status label{
115
  text-transform:uppercase;
116
  font-weight:700;
117
  position:relative;
118
  color:#999
119
  }
120
- #cn_app_status label.cn-active{
121
  color:#1ca98a
122
  }
123
- #cn_app_status label.cn-active:before{
124
  background-color:#1ca98a;
125
  box-shadow:0 0 0 2px #1ca98a
126
  }
127
- #cn_app_status label.cn-inactive{
128
  color:red
129
  }
130
- #cn_app_status label.cn-inactive:before{
131
  background-color:red;
132
  box-shadow:0 0 0 2px red
133
  }
134
- #cn_app_status label:before{
135
  background-color:#999;
136
  width:10px;
137
  height:10px;
@@ -145,23 +151,23 @@
145
  position:relative;
146
  top:-2px
147
  }
148
- #cn_colors_bar_opacity_range{
149
  vertical-align:middle;
150
  margin-right:10px
151
  }
152
- .cn-toggle-container .cn-toggle-item{
153
  font-size:14px;
154
  display:block;
155
  margin-bottom:20px;
156
  cursor:default
157
  }
158
- .cn-toggle-container .cn-toggle-item input{
159
  display:none
160
  }
161
- .cn-toggle-container .cn-toggle-item span{
162
  display:block
163
  }
164
- .cn-toggle-container .cn-toggle-item .cn-toggle-heading{
165
  color:#2271b1;
166
  transition-property:border,background,color;
167
  transition-duration:.05s;
@@ -187,7 +193,7 @@
187
  transition: transform 0.2s;
188
  position: absolute;
189
  }
190
- .cn-toggle-container .cn-toggle-item .cn-toggle-body{
191
  overflow:hidden;
192
  transition:max-height .3s;
193
  max-height:0;
@@ -195,19 +201,19 @@
195
  cursor:default;
196
  padding-left: 20px;
197
  }
198
- .cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-heading:before{
199
  transform: rotate(135deg);
200
  }
201
- .cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-body{
202
  max-height:100vh
203
  }
204
- @media only screen and (max-width:959px){
205
- .cookie-notice-sidebar{
206
  width:100%;
207
  float:none;
208
  margin:20px 0
209
  }
210
- .cookie-notice-settings{
211
  margin-right:0
212
  }
213
- }
1
+ .cookie-notice-sidebar {
2
  float:right;
3
  width:280px;
4
  margin:20px -300px 20px 20px;
5
  position:relative
6
  }
7
+ .cookie-notice-sidebar .inner {
8
  padding:1.33em
9
  }
10
+ .cookie-notice-sidebar>div:not(:last-child) {
11
  margin-bottom:3em
12
  }
13
+ .cookie-notice-sidebar .inner img {
14
  max-width:80%;
15
  height:auto;
16
  display:block;
17
  margin:20px auto
18
  }
19
+ .cookie-notice-credits {
20
  background:#fff;
21
  box-shadow:0 0 0 1px rgba(0,0,0,.05)
22
  }
23
+ .cookie-notice-credits .inner {
24
  text-align:center;
25
  margin:0
26
  }
27
+ .button.cn-button {
28
  background-color:#20c19e;
29
  border-color:#20c19e
30
  }
31
+ .button.cn-button:active,.button.cn-button:focus,.button.cn-button:hover {
32
  background-color:#1ca98a;
33
  border-color:#1ca98a
34
  }
35
+ .button.cn-button:focus {
36
  box-shadow:0 0 0 1px #fff,0 0 0 3px #20c19e
37
  }
38
+ .cookie-notice-settings .cookie-notice-credits h2 {
39
  border:none;
40
  padding-bottom:0
41
  }
42
+ .cookie-notice-credits h3 {
43
  font-size:14px;
44
  line-height:1.4;
45
  margin:0;
46
  padding:.66em 1.33em;
47
  border-bottom:1px solid #eee
48
  }
49
+ .cookie-notice-settings .df-credits form {
50
  min-width:260px;
51
  margin-bottom:1em
52
  }
53
+ .cookie-notice-settings .df-credits form input {
54
  margin:0;
55
  padding:0
56
  }
57
+ .cookie-notice-settings {
58
  margin-right:300px
59
  }
60
+ .cookie-notice-settings hr,.df-credits hr {
61
  border:solid #eee;
62
  border-width:1px 0 0;
63
  clear:both;
64
  height:0
65
  }
66
+ .cookie-notice-settings form {
67
  float:left;
68
  min-width:463px;
69
  width:100%
70
  }
71
+ .cookie-notice-settings form.cn-options-disabled h2:not(:first-of-type),
72
+ .cookie-notice-settings form.cn-options-disabled table:not(:first-of-type),
73
+ form.cn-options-submit-disabled .submit {
74
+ opacity: 0.5;
75
+ pointer-events: none;
76
+ }
77
+ .cookie-notice-settings form h2 {
78
  margin:1.5em 0;
79
  padding-bottom:1em;
80
  border-bottom:1px solid #ccc
81
  }
82
+ .cookie-notice-settings .ui-button {
83
  margin-bottom:5px
84
  }
85
+ .cookie-notice-settings .description {
86
  font-size:13px;
87
  margin-bottom:8px
88
  }
89
+ .cookie-notice-settings .description strong {
90
  color:#444
91
  }
92
+ #cn_colors label {
93
  min-width:10em;
94
  display:inline-block
95
  }
96
+ #cn_colors div {
97
  vertical-align:middle
98
  }
99
+ #cn_refuse_code .nav-tab-wrapper {
100
  padding-top:0
101
  }
102
+ #cn_refuse_code .refuse-code-tab {
103
  display:none
104
  }
105
+ #cn_refuse_code .refuse-code-tab.active {
106
  display:block
107
  }
108
+ #cn_refuse_code .refuse-code-tab .description {
109
  margin-top:10px
110
  }
111
+ .cn_compliance_status {
112
  margin-right:15px
113
  }
114
+ #cn_app_status .cn_compliance_status label {
115
  margin-left:5px!important
116
  }
117
+ #cn_app_status {
118
  margin-bottom:30px
119
  }
120
+ #cn_app_status label {
121
  text-transform:uppercase;
122
  font-weight:700;
123
  position:relative;
124
  color:#999
125
  }
126
+ #cn_app_status label.cn-active {
127
  color:#1ca98a
128
  }
129
+ #cn_app_status label.cn-active:before {
130
  background-color:#1ca98a;
131
  box-shadow:0 0 0 2px #1ca98a
132
  }
133
+ #cn_app_status label.cn-inactive {
134
  color:red
135
  }
136
+ #cn_app_status label.cn-inactive:before {
137
  background-color:red;
138
  box-shadow:0 0 0 2px red
139
  }
140
+ #cn_app_status label:before {
141
  background-color:#999;
142
  width:10px;
143
  height:10px;
151
  position:relative;
152
  top:-2px
153
  }
154
+ #cn_colors_bar_opacity_range {
155
  vertical-align:middle;
156
  margin-right:10px
157
  }
158
+ .cn-toggle-container .cn-toggle-item {
159
  font-size:14px;
160
  display:block;
161
  margin-bottom:20px;
162
  cursor:default
163
  }
164
+ .cn-toggle-container .cn-toggle-item input {
165
  display:none
166
  }
167
+ .cn-toggle-container .cn-toggle-item span {
168
  display:block
169
  }
170
+ .cn-toggle-container .cn-toggle-item .cn-toggle-heading {
171
  color:#2271b1;
172
  transition-property:border,background,color;
173
  transition-duration:.05s;
193
  transition: transform 0.2s;
194
  position: absolute;
195
  }
196
+ .cn-toggle-container .cn-toggle-item .cn-toggle-body {
197
  overflow:hidden;
198
  transition:max-height .3s;
199
  max-height:0;
201
  cursor:default;
202
  padding-left: 20px;
203
  }
204
+ .cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-heading:before {
205
  transform: rotate(135deg);
206
  }
207
+ .cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-body {
208
  max-height:100vh
209
  }
210
+ @media only screen and (max-width:959px) {
211
+ .cookie-notice-sidebar {
212
  width:100%;
213
  float:none;
214
  margin:20px 0
215
  }
216
+ .cookie-notice-settings {
217
  margin-right:0
218
  }
219
+ }
css/admin.min.css CHANGED
@@ -1 +1 @@
1
- .cookie-notice-sidebar{float:right;width:280px;margin:20px -300px 20px 20px;position:relative}.cookie-notice-sidebar .inner{padding:1.33em}.cookie-notice-sidebar>div:not(:last-child){margin-bottom:3em}.cookie-notice-sidebar .inner img{max-width:80%;height:auto;display:block;margin:20px auto}.cookie-notice-credits{background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.05)}.cookie-notice-credits .inner{text-align:center;margin:0}.button.cn-button{background-color:#20c19e;border-color:#20c19e}.button.cn-button:active,.button.cn-button:focus,.button.cn-button:hover{background-color:#1ca98a;border-color:#1ca98a}.button.cn-button:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #20c19e}.cookie-notice-settings .cookie-notice-credits h2{border:none;padding-bottom:0}.cookie-notice-credits h3{font-size:14px;line-height:1.4;margin:0;padding:.66em 1.33em;border-bottom:1px solid #eee}.cookie-notice-settings .df-credits form{min-width:260px;margin-bottom:1em}.cookie-notice-settings .df-credits form input{margin:0;padding:0}.cookie-notice-settings{margin-right:300px}.cookie-notice-settings hr,.df-credits hr{border:solid #eee;border-width:1px 0 0;clear:both;height:0}.cookie-notice-settings form{float:left;min-width:463px;width:100%}.cookie-notice-settings form h2{margin:1.5em 0;padding-bottom:1em;border-bottom:1px solid #ccc}.cookie-notice-settings .ui-button{margin-bottom:5px}.cookie-notice-settings .description{font-size:13px;margin-bottom:8px}.cookie-notice-settings .description strong{color:#444}#cn_colors label{min-width:10em;display:inline-block}#cn_colors div{vertical-align:middle}#cn_refuse_code .nav-tab-wrapper{padding-top:0}#cn_refuse_code .refuse-code-tab{display:none}#cn_refuse_code .refuse-code-tab.active{display:block}#cn_refuse_code .refuse-code-tab .description{margin-top:10px}.cn_compliance_status{margin-right:15px}#cn_app_status .cn_compliance_status label{margin-left:5px!important}#cn_app_status{margin-bottom:30px}#cn_app_status label{text-transform:uppercase;font-weight:700;position:relative;color:#999}#cn_app_status label.cn-active{color:#1ca98a}#cn_app_status label.cn-active:before{background-color:#1ca98a;box-shadow:0 0 0 2px #1ca98a}#cn_app_status label.cn-inactive{color:red}#cn_app_status label.cn-inactive:before{background-color:red;box-shadow:0 0 0 2px red}#cn_app_status label:before{background-color:#999;width:10px;height:10px;border-radius:10px;content:'';display:inline-block;vertical-align:middle;margin-right:10px;box-shadow:0 0 0 2px #999;border:2px solid #fff;position:relative;top:-2px}#cn_colors_bar_opacity_range{vertical-align:middle;margin-right:10px}.cn-toggle-container .cn-toggle-item{font-size:14px;display:block;margin-bottom:20px;cursor:default}.cn-toggle-container .cn-toggle-item input{display:none}.cn-toggle-container .cn-toggle-item span{display:block}.cn-toggle-container .cn-toggle-item .cn-toggle-heading{color:#2271b1;transition-property:border,background,color;transition-duration:.05s;transition-timing-function:ease-in-out;text-decoration:underline;font-weight:600;cursor:pointer;position:relative;padding-left:20px}.cn-toggle-container .cn-toggle-item .cn-toggle-heading:before{border-style:solid;border-width:2px 2px 0 0;content:'';display:inline-block;height:6px;width:6px;position:relative;top:5px;left:0;vertical-align:top;transform:rotate(45deg);transition:transform 0.2s;position:absolute}.cn-toggle-container .cn-toggle-item .cn-toggle-body{overflow:hidden;transition:max-height .3s;max-height:0;margin-top:10px;cursor:default;padding-left:20px}.cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-heading:before{transform:rotate(135deg)}.cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-body{max-height:100vh}@media only screen and (max-width:959px){.cookie-notice-sidebar{width:100%;float:none;margin:20px 0}.cookie-notice-settings{margin-right:0}}
1
+ .cookie-notice-sidebar{float:right;width:280px;margin:20px -300px 20px 20px;position:relative}.cookie-notice-sidebar .inner{padding:1.33em}.cookie-notice-sidebar>div:not(:last-child){margin-bottom:3em}.cookie-notice-sidebar .inner img{max-width:80%;height:auto;display:block;margin:20px auto}.cookie-notice-credits{background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.05)}.cookie-notice-credits .inner{text-align:center;margin:0}.button.cn-button{background-color:#20c19e;border-color:#20c19e}.button.cn-button:active,.button.cn-button:focus,.button.cn-button:hover{background-color:#1ca98a;border-color:#1ca98a}.button.cn-button:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #20c19e}.cookie-notice-settings .cookie-notice-credits h2{border:none;padding-bottom:0}.cookie-notice-credits h3{font-size:14px;line-height:1.4;margin:0;padding:.66em 1.33em;border-bottom:1px solid #eee}.cookie-notice-settings .df-credits form{min-width:260px;margin-bottom:1em}.cookie-notice-settings .df-credits form input{margin:0;padding:0}.cookie-notice-settings{margin-right:300px}.cookie-notice-settings hr,.df-credits hr{border:solid #eee;border-width:1px 0 0;clear:both;height:0}.cookie-notice-settings form{float:left;min-width:463px;width:100%}.cookie-notice-settings form.cn-options-disabled h2:not(:first-of-type),.cookie-notice-settings form.cn-options-disabled table:not(:first-of-type),form.cn-options-submit-disabled .submit{opacity:.5;pointer-events:none}.cookie-notice-settings form h2{margin:1.5em 0;padding-bottom:1em;border-bottom:1px solid #ccc}.cookie-notice-settings .ui-button{margin-bottom:5px}.cookie-notice-settings .description{font-size:13px;margin-bottom:8px}.cookie-notice-settings .description strong{color:#444}#cn_colors label{min-width:10em;display:inline-block}#cn_colors div{vertical-align:middle}#cn_refuse_code .nav-tab-wrapper{padding-top:0}#cn_refuse_code .refuse-code-tab{display:none}#cn_refuse_code .refuse-code-tab.active{display:block}#cn_refuse_code .refuse-code-tab .description{margin-top:10px}.cn_compliance_status{margin-right:15px}#cn_app_status .cn_compliance_status label{margin-left:5px!important}#cn_app_status{margin-bottom:30px}#cn_app_status label{text-transform:uppercase;font-weight:700;position:relative;color:#999}#cn_app_status label.cn-active{color:#1ca98a}#cn_app_status label.cn-active:before{background-color:#1ca98a;box-shadow:0 0 0 2px #1ca98a}#cn_app_status label.cn-inactive{color:red}#cn_app_status label.cn-inactive:before{background-color:red;box-shadow:0 0 0 2px red}#cn_app_status label:before{background-color:#999;width:10px;height:10px;border-radius:10px;content:'';display:inline-block;vertical-align:middle;margin-right:10px;box-shadow:0 0 0 2px #999;border:2px solid #fff;position:relative;top:-2px}#cn_colors_bar_opacity_range{vertical-align:middle;margin-right:10px}.cn-toggle-container .cn-toggle-item{font-size:14px;display:block;margin-bottom:20px;cursor:default}.cn-toggle-container .cn-toggle-item input{display:none}.cn-toggle-container .cn-toggle-item span{display:block}.cn-toggle-container .cn-toggle-item .cn-toggle-heading{color:#2271b1;transition-property:border,background,color;transition-duration:.05s;transition-timing-function:ease-in-out;text-decoration:underline;font-weight:600;cursor:pointer;position:relative;padding-left:20px}.cn-toggle-container .cn-toggle-item .cn-toggle-heading:before{border-style:solid;border-width:2px 2px 0 0;content:'';display:inline-block;height:6px;width:6px;position:relative;top:5px;left:0;vertical-align:top;transform:rotate(45deg);transition:transform 0.2s;position:absolute}.cn-toggle-container .cn-toggle-item .cn-toggle-body{overflow:hidden;transition:max-height .3s;max-height:0;margin-top:10px;cursor:default;padding-left:20px}.cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-heading:before{transform:rotate(135deg)}.cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-body{max-height:100vh}@media only screen and (max-width:959px){.cookie-notice-sidebar{width:100%;float:none;margin:20px 0}.cookie-notice-settings{margin-right:0}}
css/front.css CHANGED
@@ -12,63 +12,51 @@
12
  font-weight: normal;
13
  font-family: -apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;
14
  }
15
-
16
  #cookie-notice,
17
  #cookie-notice * {
18
  -webkit-box-sizing: border-box;
19
  -moz-box-sizing: border-box;
20
  box-sizing: border-box;
21
  }
22
-
23
  #cookie-notice.cn-animated {
24
  -webkit-animation-duration: 0.5s !important;
25
  animation-duration: 0.5s !important;
26
  -webkit-animation-fill-mode: both;
27
  animation-fill-mode: both;
28
  }
29
-
30
  #cookie-notice.cn-animated.cn-effect-none {
31
  -webkit-animation-duration: 0.001s !important;
32
  animation-duration: 0.001s !important;
33
  }
34
-
35
  #cookie-notice .cookie-notice-container {
36
  display: block;
37
  }
38
-
39
  #cookie-notice.cookie-notice-hidden .cookie-notice-container {
40
  display: none;
41
  }
42
-
43
  #cookie-notice .cookie-revoke-container {
44
  display: block;
45
  }
46
-
47
  #cookie-notice.cookie-revoke-hidden .cookie-revoke-container {
48
  display: none;
49
  }
50
-
51
  .cn-position-top {
52
  top: 0;
53
  }
54
-
55
  .cn-position-bottom {
56
  bottom: 0;
57
  }
58
-
59
  .cookie-notice-container {
60
  padding: 15px 30px;
61
  text-align: center;
62
  width: 100%;
63
  z-index: 2;
64
  }
65
-
66
  .cookie-revoke-container {
67
  padding: 15px 30px;
68
  width: 100%;
69
  z-index: 1;
70
  }
71
-
72
  .cn-close-icon {
73
  position: absolute;
74
  right: 15px;
@@ -79,9 +67,8 @@
79
  opacity: 0.5;
80
  padding: 10px;
81
  outline: none;
82
- cursor: pointer;
83
  }
84
-
85
  .cn-close-icon:hover {
86
  opacity: 1;
87
  }
@@ -100,14 +87,12 @@
100
  .cn-close-icon:after {
101
  transform: rotate(-45deg);
102
  }
103
-
104
  #cookie-notice .cn-revoke-cookie {
105
  margin: 0;
106
  }
107
-
108
  #cookie-notice .cn-button {
109
  margin: 0 0 0 10px;
110
- display: inline-block;
111
  }
112
  #cookie-notice .cn-button:not(.cn-button-custom) {
113
  font-family: -apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;
@@ -134,60 +119,49 @@
134
  line-height: 1;
135
  color: inherit;
136
  }
137
-
138
  .cn-text-container {
139
  margin: 0 0 6px 0;
140
  }
141
-
142
  .cn-text-container,
143
  .cn-buttons-container {
144
  display: inline-block;
145
  }
146
-
147
  #cookie-notice.cookie-notice-visible.cn-effect-none,
148
  #cookie-notice.cookie-revoke-visible.cn-effect-none {
149
  -webkit-animation-name: fadeIn;
150
  animation-name: fadeIn;
151
  }
152
-
153
  #cookie-notice.cn-effect-none {
154
  -webkit-animation-name: fadeOut;
155
  animation-name: fadeOut;
156
  }
157
-
158
  #cookie-notice.cookie-notice-visible.cn-effect-fade,
159
  #cookie-notice.cookie-revoke-visible.cn-effect-fade {
160
  -webkit-animation-name: fadeIn;
161
  animation-name: fadeIn;
162
  }
163
-
164
  #cookie-notice.cn-effect-fade {
165
  -webkit-animation-name: fadeOut;
166
  animation-name: fadeOut;
167
  }
168
-
169
  #cookie-notice.cookie-notice-visible.cn-effect-slide,
170
  #cookie-notice.cookie-revoke-visible.cn-effect-slide{
171
  -webkit-animation-name: slideInUp;
172
  animation-name: slideInUp;
173
  }
174
-
175
  #cookie-notice.cn-effect-slide {
176
  -webkit-animation-name: slideOutDown;
177
  animation-name: slideOutDown;
178
  }
179
-
180
  #cookie-notice.cookie-notice-visible.cn-position-top.cn-effect-slide,
181
  #cookie-notice.cookie-revoke-visible.cn-position-top.cn-effect-slide {
182
  -webkit-animation-name: slideInDown;
183
  animation-name: slideInDown;
184
  }
185
-
186
  #cookie-notice.cn-position-top.cn-effect-slide {
187
  -webkit-animation-name: slideOutUp;
188
  animation-name: slideOutUp;
189
  }
190
-
191
  @-webkit-keyframes fadeIn {
192
  from {
193
  opacity: 0;
@@ -197,7 +171,6 @@
197
  opacity: 1;
198
  }
199
  }
200
-
201
  @keyframes fadeIn {
202
  from {
203
  opacity: 0;
@@ -207,7 +180,6 @@
207
  opacity: 1;
208
  }
209
  }
210
-
211
  @-webkit-keyframes fadeOut {
212
  from {
213
  opacity: 1;
@@ -217,7 +189,6 @@
217
  opacity: 0;
218
  }
219
  }
220
-
221
  @keyframes fadeOut {
222
  from {
223
  opacity: 1;
@@ -227,7 +198,6 @@
227
  opacity: 0;
228
  }
229
  }
230
-
231
  @-webkit-keyframes slideInUp {
232
  from {
233
  -webkit-transform: translate3d(0, 100%, 0);
@@ -240,7 +210,6 @@
240
  transform: translate3d(0, 0, 0);
241
  }
242
  }
243
-
244
  @keyframes slideInUp {
245
  from {
246
  -webkit-transform: translate3d(0, 100%, 0);
@@ -253,7 +222,6 @@
253
  transform: translate3d(0, 0, 0);
254
  }
255
  }
256
-
257
  @-webkit-keyframes slideOutDown {
258
  from {
259
  -webkit-transform: translate3d(0, 0, 0);
@@ -266,7 +234,6 @@
266
  transform: translate3d(0, 100%, 0);
267
  }
268
  }
269
-
270
  @keyframes slideOutDown {
271
  from {
272
  -webkit-transform: translate3d(0, 0, 0);
@@ -279,7 +246,6 @@
279
  transform: translate3d(0, 100%, 0);
280
  }
281
  }
282
-
283
  @-webkit-keyframes slideInDown {
284
  from {
285
  -webkit-transform: translate3d(0, -100%, 0);
@@ -292,7 +258,6 @@
292
  transform: translate3d(0, 0, 0);
293
  }
294
  }
295
-
296
  @keyframes slideInDown {
297
  from {
298
  -webkit-transform: translate3d(0, -100%, 0);
@@ -305,7 +270,6 @@
305
  transform: translate3d(0, 0, 0);
306
  }
307
  }
308
-
309
  @-webkit-keyframes slideOutUp {
310
  from {
311
  -webkit-transform: translate3d(0, 0, 0);
@@ -318,7 +282,6 @@
318
  transform: translate3d(0, -100%, 0);
319
  }
320
  }
321
-
322
  @keyframes slideOutUp {
323
  from {
324
  -webkit-transform: translate3d(0, 0, 0);
@@ -331,7 +294,6 @@
331
  transform: translate3d(0, -100%, 0);
332
  }
333
  }
334
-
335
  @media all and (max-width: 900px) {
336
  .cookie-notice-container #cn-notice-text {
337
  display: block;
@@ -343,7 +305,6 @@
343
  margin: 0 5px 5px 5px;
344
  }
345
  }
346
-
347
  @media all and (max-width: 480px) {
348
  .cookie-notice-container,
349
  .cookie-revoke-container {
12
  font-weight: normal;
13
  font-family: -apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;
14
  }
 
15
  #cookie-notice,
16
  #cookie-notice * {
17
  -webkit-box-sizing: border-box;
18
  -moz-box-sizing: border-box;
19
  box-sizing: border-box;
20
  }
 
21
  #cookie-notice.cn-animated {
22
  -webkit-animation-duration: 0.5s !important;
23
  animation-duration: 0.5s !important;
24
  -webkit-animation-fill-mode: both;
25
  animation-fill-mode: both;
26
  }
 
27
  #cookie-notice.cn-animated.cn-effect-none {
28
  -webkit-animation-duration: 0.001s !important;
29
  animation-duration: 0.001s !important;
30
  }
 
31
  #cookie-notice .cookie-notice-container {
32
  display: block;
33
  }
 
34
  #cookie-notice.cookie-notice-hidden .cookie-notice-container {
35
  display: none;
36
  }
 
37
  #cookie-notice .cookie-revoke-container {
38
  display: block;
39
  }
 
40
  #cookie-notice.cookie-revoke-hidden .cookie-revoke-container {
41
  display: none;
42
  }
 
43
  .cn-position-top {
44
  top: 0;
45
  }
 
46
  .cn-position-bottom {
47
  bottom: 0;
48
  }
 
49
  .cookie-notice-container {
50
  padding: 15px 30px;
51
  text-align: center;
52
  width: 100%;
53
  z-index: 2;
54
  }
 
55
  .cookie-revoke-container {
56
  padding: 15px 30px;
57
  width: 100%;
58
  z-index: 1;
59
  }
 
60
  .cn-close-icon {
61
  position: absolute;
62
  right: 15px;
67
  opacity: 0.5;
68
  padding: 10px;
69
  outline: none;
70
+ cursor: pointer;
71
  }
 
72
  .cn-close-icon:hover {
73
  opacity: 1;
74
  }
87
  .cn-close-icon:after {
88
  transform: rotate(-45deg);
89
  }
 
90
  #cookie-notice .cn-revoke-cookie {
91
  margin: 0;
92
  }
 
93
  #cookie-notice .cn-button {
94
  margin: 0 0 0 10px;
95
+ display: inline-block;
96
  }
97
  #cookie-notice .cn-button:not(.cn-button-custom) {
98
  font-family: -apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;
119
  line-height: 1;
120
  color: inherit;
121
  }
 
122
  .cn-text-container {
123
  margin: 0 0 6px 0;
124
  }
 
125
  .cn-text-container,
126
  .cn-buttons-container {
127
  display: inline-block;
128
  }
 
129
  #cookie-notice.cookie-notice-visible.cn-effect-none,
130
  #cookie-notice.cookie-revoke-visible.cn-effect-none {
131
  -webkit-animation-name: fadeIn;
132
  animation-name: fadeIn;
133
  }
 
134
  #cookie-notice.cn-effect-none {
135
  -webkit-animation-name: fadeOut;
136
  animation-name: fadeOut;
137
  }
 
138
  #cookie-notice.cookie-notice-visible.cn-effect-fade,
139
  #cookie-notice.cookie-revoke-visible.cn-effect-fade {
140
  -webkit-animation-name: fadeIn;
141
  animation-name: fadeIn;
142
  }
 
143
  #cookie-notice.cn-effect-fade {
144
  -webkit-animation-name: fadeOut;
145
  animation-name: fadeOut;
146
  }
 
147
  #cookie-notice.cookie-notice-visible.cn-effect-slide,
148
  #cookie-notice.cookie-revoke-visible.cn-effect-slide{
149
  -webkit-animation-name: slideInUp;
150
  animation-name: slideInUp;
151
  }
 
152
  #cookie-notice.cn-effect-slide {
153
  -webkit-animation-name: slideOutDown;
154
  animation-name: slideOutDown;
155
  }
 
156
  #cookie-notice.cookie-notice-visible.cn-position-top.cn-effect-slide,
157
  #cookie-notice.cookie-revoke-visible.cn-position-top.cn-effect-slide {
158
  -webkit-animation-name: slideInDown;
159
  animation-name: slideInDown;
160
  }
 
161
  #cookie-notice.cn-position-top.cn-effect-slide {
162
  -webkit-animation-name: slideOutUp;
163
  animation-name: slideOutUp;
164
  }
 
165
  @-webkit-keyframes fadeIn {
166
  from {
167
  opacity: 0;
171
  opacity: 1;
172
  }
173
  }
 
174
  @keyframes fadeIn {
175
  from {
176
  opacity: 0;
180
  opacity: 1;
181
  }
182
  }
 
183
  @-webkit-keyframes fadeOut {
184
  from {
185
  opacity: 1;
189
  opacity: 0;
190
  }
191
  }
 
192
  @keyframes fadeOut {
193
  from {
194
  opacity: 1;
198
  opacity: 0;
199
  }
200
  }
 
201
  @-webkit-keyframes slideInUp {
202
  from {
203
  -webkit-transform: translate3d(0, 100%, 0);
210
  transform: translate3d(0, 0, 0);
211
  }
212
  }
 
213
  @keyframes slideInUp {
214
  from {
215
  -webkit-transform: translate3d(0, 100%, 0);
222
  transform: translate3d(0, 0, 0);
223
  }
224
  }
 
225
  @-webkit-keyframes slideOutDown {
226
  from {
227
  -webkit-transform: translate3d(0, 0, 0);
234
  transform: translate3d(0, 100%, 0);
235
  }
236
  }
 
237
  @keyframes slideOutDown {
238
  from {
239
  -webkit-transform: translate3d(0, 0, 0);
246
  transform: translate3d(0, 100%, 0);
247
  }
248
  }
 
249
  @-webkit-keyframes slideInDown {
250
  from {
251
  -webkit-transform: translate3d(0, -100%, 0);
258
  transform: translate3d(0, 0, 0);
259
  }
260
  }
 
261
  @keyframes slideInDown {
262
  from {
263
  -webkit-transform: translate3d(0, -100%, 0);
270
  transform: translate3d(0, 0, 0);
271
  }
272
  }
 
273
  @-webkit-keyframes slideOutUp {
274
  from {
275
  -webkit-transform: translate3d(0, 0, 0);
282
  transform: translate3d(0, -100%, 0);
283
  }
284
  }
 
285
  @keyframes slideOutUp {
286
  from {
287
  -webkit-transform: translate3d(0, 0, 0);
294
  transform: translate3d(0, -100%, 0);
295
  }
296
  }
 
297
  @media all and (max-width: 900px) {
298
  .cookie-notice-container #cn-notice-text {
299
  display: block;
305
  margin: 0 5px 5px 5px;
306
  }
307
  }
 
308
  @media all and (max-width: 480px) {
309
  .cookie-notice-container,
310
  .cookie-revoke-container {
css/front.min.css CHANGED
@@ -1 +1 @@
1
- #cookie-notice{position:fixed;min-width:100%;height:auto;z-index:100000;font-size:13px;letter-spacing:0;line-height:20px;left:0;text-align:center;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif}#cookie-notice,#cookie-notice *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#cookie-notice.cn-animated{-webkit-animation-duration:.5s!important;animation-duration:.5s!important;-webkit-animation-fill-mode:both;animation-fill-mode:both}#cookie-notice.cn-animated.cn-effect-none{-webkit-animation-duration:.001s!important;animation-duration:.001s!important}#cookie-notice .cookie-notice-container{display:block}#cookie-notice.cookie-notice-hidden .cookie-notice-container{display:none}#cookie-notice .cookie-revoke-container{display:block}#cookie-notice.cookie-revoke-hidden .cookie-revoke-container{display:none}.cn-position-top{top:0}.cn-position-bottom{bottom:0}.cookie-notice-container{padding:15px 30px;text-align:center;width:100%;z-index:2}.cookie-revoke-container{padding:15px 30px;width:100%;z-index:1}.cn-close-icon{position:absolute;right:15px;top:50%;margin-top:-10px;width:15px;height:15px;opacity:.5;padding:10px;outline:none;cursor:pointer}.cn-close-icon:hover{opacity:1}.cn-close-icon:before,.cn-close-icon:after{position:absolute;content:' ';height:15px;width:2px;top:3px;background-color:rgba(128,128,128,1)}.cn-close-icon:before{transform:rotate(45deg)}.cn-close-icon:after{transform:rotate(-45deg)}#cookie-notice .cn-revoke-cookie{margin:0}#cookie-notice .cn-button{margin:0 0 0 10px;display:inline-block}#cookie-notice .cn-button:not(.cn-button-custom){font-family:-apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;font-weight:400;font-size:13px;letter-spacing:.25px;line-height:20px;margin:0 0 0 10px;text-align:center;text-transform:none;display:inline-block;cursor:pointer;touch-action:manipulation;white-space:nowrap;outline:none;box-shadow:none;text-shadow:none;border:none;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;text-decoration:none;padding:8.5px 10px;line-height:1;color:inherit}.cn-text-container{margin:0 0 6px}.cn-text-container,.cn-buttons-container{display:inline-block}#cookie-notice.cookie-notice-visible.cn-effect-none,#cookie-notice.cookie-revoke-visible.cn-effect-none{-webkit-animation-name:fadeIn;animation-name:fadeIn}#cookie-notice.cn-effect-none{-webkit-animation-name:fadeOut;animation-name:fadeOut}#cookie-notice.cookie-notice-visible.cn-effect-fade,#cookie-notice.cookie-revoke-visible.cn-effect-fade{-webkit-animation-name:fadeIn;animation-name:fadeIn}#cookie-notice.cn-effect-fade{-webkit-animation-name:fadeOut;animation-name:fadeOut}#cookie-notice.cookie-notice-visible.cn-effect-slide,#cookie-notice.cookie-revoke-visible.cn-effect-slide{-webkit-animation-name:slideInUp;animation-name:slideInUp}#cookie-notice.cn-effect-slide{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}#cookie-notice.cookie-notice-visible.cn-position-top.cn-effect-slide,#cookie-notice.cookie-revoke-visible.cn-position-top.cn-effect-slide{-webkit-animation-name:slideInDown;animation-name:slideInDown}#cookie-notice.cn-position-top.cn-effect-slide{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeOut{from{opacity:1}to{opacity:0}}@keyframes fadeOut{from{opacity:1}to{opacity:0}}@-webkit-keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@-webkit-keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@-webkit-keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@-webkit-keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@media all and (max-width: 900px){.cookie-notice-container #cn-notice-text{display:block}.cookie-notice-container #cn-notice-buttons{display:block}#cookie-notice .cn-button{margin:0 5px 5px}}@media all and (max-width: 480px){.cookie-notice-container,.cookie-revoke-container{padding:15px 25px}}
1
+ #cookie-notice{position:fixed;min-width:100%;height:auto;z-index:100000;font-size:13px;letter-spacing:0;line-height:20px;left:0;text-align:center;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif}#cookie-notice,#cookie-notice *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#cookie-notice.cn-animated{-webkit-animation-duration:0.5s!important;animation-duration:0.5s!important;-webkit-animation-fill-mode:both;animation-fill-mode:both}#cookie-notice.cn-animated.cn-effect-none{-webkit-animation-duration:0.001s!important;animation-duration:0.001s!important}#cookie-notice .cookie-notice-container{display:block}#cookie-notice.cookie-notice-hidden .cookie-notice-container{display:none}#cookie-notice .cookie-revoke-container{display:block}#cookie-notice.cookie-revoke-hidden .cookie-revoke-container{display:none}.cn-position-top{top:0}.cn-position-bottom{bottom:0}.cookie-notice-container{padding:15px 30px;text-align:center;width:100%;z-index:2}.cookie-revoke-container{padding:15px 30px;width:100%;z-index:1}.cn-close-icon{position:absolute;right:15px;top:50%;margin-top:-10px;width:15px;height:15px;opacity:.5;padding:10px;outline:none;cursor:pointer}.cn-close-icon:hover{opacity:1}.cn-close-icon:before,.cn-close-icon:after{position:absolute;content:' ';height:15px;width:2px;top:3px;background-color:rgba(128,128,128,1)}.cn-close-icon:before{transform:rotate(45deg)}.cn-close-icon:after{transform:rotate(-45deg)}#cookie-notice .cn-revoke-cookie{margin:0}#cookie-notice .cn-button{margin:0 0 0 10px;display:inline-block}#cookie-notice .cn-button:not(.cn-button-custom){font-family:-apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;font-weight:400;font-size:13px;letter-spacing:.25px;line-height:20px;margin:0 0 0 10px;text-align:center;text-transform:none;display:inline-block;cursor:pointer;touch-action:manipulation;white-space:nowrap;outline:none;box-shadow:none;text-shadow:none;border:none;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;text-decoration:none;padding:8.5px 10px;line-height:1;color:inherit}.cn-text-container{margin:0 0 6px 0}.cn-text-container,.cn-buttons-container{display:inline-block}#cookie-notice.cookie-notice-visible.cn-effect-none,#cookie-notice.cookie-revoke-visible.cn-effect-none{-webkit-animation-name:fadeIn;animation-name:fadeIn}#cookie-notice.cn-effect-none{-webkit-animation-name:fadeOut;animation-name:fadeOut}#cookie-notice.cookie-notice-visible.cn-effect-fade,#cookie-notice.cookie-revoke-visible.cn-effect-fade{-webkit-animation-name:fadeIn;animation-name:fadeIn}#cookie-notice.cn-effect-fade{-webkit-animation-name:fadeOut;animation-name:fadeOut}#cookie-notice.cookie-notice-visible.cn-effect-slide,#cookie-notice.cookie-revoke-visible.cn-effect-slide{-webkit-animation-name:slideInUp;animation-name:slideInUp}#cookie-notice.cn-effect-slide{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}#cookie-notice.cookie-notice-visible.cn-position-top.cn-effect-slide,#cookie-notice.cookie-revoke-visible.cn-position-top.cn-effect-slide{-webkit-animation-name:slideInDown;animation-name:slideInDown}#cookie-notice.cn-position-top.cn-effect-slide{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeOut{from{opacity:1}to{opacity:0}}@keyframes fadeOut{from{opacity:1}to{opacity:0}}@-webkit-keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@-webkit-keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@-webkit-keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@-webkit-keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@media all and (max-width:900px){.cookie-notice-container #cn-notice-text{display:block}.cookie-notice-container #cn-notice-buttons{display:block}#cookie-notice .cn-button{margin:0 5px 5px 5px}}@media all and (max-width:480px){.cookie-notice-container,.cookie-revoke-container{padding:15px 25px}}
includes/bot-detect.php CHANGED
@@ -71,7 +71,7 @@ class Cookie_Notice_Bot_Detect {
71
  */
72
  public function init() {
73
  // break on admin side
74
- if ( is_admin() && ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) )
75
  return;
76
 
77
  $this->ua_http_headers = $this->get_headers_list();
71
  */
72
  public function init() {
73
  // break on admin side
74
+ if ( is_admin() && ! wp_doing_ajax() )
75
  return;
76
 
77
  $this->ua_http_headers = $this->get_headers_list();
includes/dashboard.php CHANGED
@@ -1,492 +1,523 @@
1
- <?php
2
-
3
- // exit if accessed directly
4
- if ( ! defined( 'ABSPATH' ) )
5
- exit;
6
-
7
- /**
8
- * Cookie_Notice_Dashboard class.
9
- *
10
- * @class Cookie_Notice_Dashboard
11
- */
12
- class Cookie_Notice_Dashboard {
13
-
14
- /**
15
- * Class constructor.
16
- *
17
- * @return void
18
- */
19
- public function __construct() {
20
- // actions
21
- add_action( 'wp_dashboard_setup', [ $this, 'wp_dashboard_setup' ], 11 );
22
- add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts_styles' ] );
23
-
24
- // site status
25
- add_filter( 'site_status_tests', array( $this, 'add_tests' ) );
26
- }
27
-
28
- /**
29
- * Initialize widget.
30
- *
31
- * @return void
32
- */
33
- public function wp_dashboard_setup() {
34
- // filter user_can_see_stats
35
- if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
36
- return;
37
-
38
- global $wp_meta_boxes;
39
-
40
- $widget_key = 'cn_dashboard_stats';
41
-
42
- // add dashboard chart widget
43
- wp_add_dashboard_widget( $widget_key, __( 'Cookie Compliance', 'cookie-notice' ), [ $this, 'dashboard_widget' ] );
44
-
45
- // attempt to place the widget at the top
46
- $normal_dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
47
-
48
- $widget_instance = array( $widget_key => $normal_dashboard[ $widget_key ] );
49
- unset( $normal_dashboard[ $widget_key ] );
50
- $sorted_dashboard = array_merge( $widget_instance, $normal_dashboard );
51
-
52
- $wp_meta_boxes['dashboard']['normal']['core'] = $sorted_dashboard;
53
- }
54
-
55
- /**
56
- * Enqueue admin scripts and styles.
57
- *
58
- * @param string $pagenow
59
- * @return void
60
- */
61
- public function admin_scripts_styles( $pagenow ) {
62
- if ( $pagenow !== 'index.php' )
63
- return;
64
-
65
- // filter user_can_see_stats
66
- if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
67
- return;
68
-
69
- $analytics = get_option( 'cookie_notice_app_analytics' );
70
- $date_format = get_option( 'date_format' );
71
-
72
- // styles
73
- wp_enqueue_style( 'cn-admin-dashboard', plugins_url( '../css/admin-dashboard.css', __FILE__ ), [], Cookie_Notice()->defaults['version'] );
74
- wp_enqueue_style( 'cn-microtip', plugins_url( '../assets/microtip/microtip.min.css', __FILE__ ), [], Cookie_Notice()->defaults['version'] );
75
-
76
- // bail if COmpliance is not active
77
- if ( Cookie_Notice()->get_status() !== 'active' )
78
- return;
79
-
80
- // scripts
81
- wp_enqueue_script( 'cn-admin-chartjs', plugins_url( '../assets/chartjs/chart.min.js', __FILE__ ), [ 'jquery' ], Cookie_Notice()->defaults['version'], true );
82
- wp_enqueue_script( 'cn-admin-dashboard', plugins_url( '../js/admin-dashboard.js', __FILE__ ), [ 'jquery', 'cn-admin-chartjs' ], Cookie_Notice()->defaults['version'], true );
83
-
84
- // cycle usage data
85
- $cycle_usage = array(
86
- 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
87
- 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0,
88
- 'days_to_go' => ! empty( $analytics['cycleUsage']->daysToGo ) ? (int) $analytics['cycleUsage']->daysToGo : 0,
89
- 'start_date' => ! empty( $analytics['cycleUsage']->startDate ) ? date_i18n( $date_format, strtotime( $analytics['cycleUsage']->startDate ) ) : '',
90
- 'end_date' => ! empty( $analytics['cycleUsage']->endDate ) ? date_i18n( $date_format, strtotime( $analytics['cycleUsage']->endDate ) ) : ''
91
- );
92
-
93
- // available visits, -1 for no pro plans
94
- $cycle_usage['visits_available'] = $cycle_usage['threshold'] ? $cycle_usage['threshold'] - $cycle_usage['visits'] : -1;
95
- $cycle_usage['threshold_used'] = $cycle_usage['threshold'] ? ( $cycle_usage['visits'] / $cycle_usage['threshold'] ) * 100 : 0;
96
- $cycle_usage['threshold_used'] = $cycle_usage['threshold_used'] > 100 ? 100 : $cycle_usage['threshold_used'];
97
-
98
- $chartdata = [
99
- 'usage' => array(
100
- 'type' => 'doughnut',
101
- 'data' => array(
102
- 'labels' => array(
103
- _x( 'Used', 'threshold limit', 'cookie-notice' ),
104
- _x( 'Free', 'threshold limit', 'cookie-notice' )
105
- ),
106
- 'datasets' => array(
107
- array(
108
- 'data' => array( $cycle_usage['visits'], $cycle_usage['visits_available'] ),
109
- // 'borderColor' => 'rgb(255, 255, 255)',
110
- 'backgroundColor' => array(
111
- 'rgb(32, 193, 158)',
112
- 'rgb(235, 233, 235)'
113
- )
114
- )
115
- )
116
- )
117
- ),
118
- 'consent-activity' => array(
119
- 'type' => 'line'
120
- )
121
- ];
122
-
123
- // warning usage color
124
- if ( $cycle_usage['threshold_used'] > 80 && $cycle_usage['threshold_used'] < 100 ) {
125
- $chartdata['usage']['data']['datasets'][0]['backgroundColor'][0] = 'rgb(255, 193, 7)';
126
- // danger usage color
127
- } elseif ( $cycle_usage['threshold_used'] == 100 ) {
128
- $chartdata['usage']['data']['datasets'][0]['backgroundColor'][0] = 'rgb(220, 53, 69)';
129
- }
130
-
131
- // echo '<pre>'; print_r( $analytics ); echo '</pre>'; exit;
132
-
133
- if ( $analytics['consentActivities'] && is_array( $analytics['consentActivities'] ) ) {
134
-
135
- $data = array(
136
- );
137
-
138
- // set default color;
139
- $color = [
140
- 'r' => 32,
141
- 'g' => 193,
142
- 'b' => 158
143
- ];
144
-
145
- $data = [
146
- 'labels' => [],
147
- 'datasets' => [
148
- 0 => array(
149
- 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 1 ),
150
- 'data' => array(),
151
- 'fill' => true,
152
- 'backgroundColor' => 'rgba(196, 196, 196, 0.3)',
153
- 'borderColor' => 'rgba(196, 196, 196, 1)',
154
- 'borderWidth' => 1.2,
155
- 'borderDash' => [],
156
- 'pointBorderColor' => 'rgba(196, 196, 196, 1)',
157
- 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
158
- 'pointBorderWidth' => 1.2
159
- ),
160
- 1 => array(
161
- 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 2 ),
162
- 'data' => array(),
163
- 'fill' => true,
164
- 'backgroundColor' => 'rgba(213, 181, 101, 0.3)',
165
- 'borderColor' => 'rgba(213, 181, 101, 1)',
166
- 'borderWidth' => 1.2,
167
- 'borderDash' => [],
168
- 'pointBorderColor' => 'rgba(213, 181, 101, 1)',
169
- 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
170
- 'pointBorderWidth' => 1.2
171
- ),
172
- 2 => array(
173
- 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 3 ),
174
- 'data' => array(),
175
- 'fill' => true,
176
- 'backgroundColor' => 'rgba(152, 145, 177, 0.3)',
177
- 'borderColor' => 'rgba(152, 145, 177, 1)',
178
- 'borderWidth' => 1.2,
179
- 'borderDash' => [],
180
- 'pointBorderColor' => 'rgba(152, 145, 177, 1)',
181
- 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
182
- 'pointBorderWidth' => 1.2
183
- ),
184
- ]
185
- ];
186
-
187
- // generate chart days
188
- $chart_date_format = 'j/m';
189
-
190
- for( $i = 30; $i > 0; $i-- ) {
191
- $data['labels'][] = date( $chart_date_format , strtotime( '-'. $i .' days' ) );
192
-
193
- $data['datasets'][0]['data'][] = 0;
194
- $data['datasets'][1]['data'][] = 0;
195
- $data['datasets'][2]['data'][] = 0;
196
- }
197
-
198
- // set consent records in charts days
199
- foreach ( $analytics['consentActivities'] as $index => $entry ) {
200
- $time = date_i18n( $chart_date_format, strtotime( $entry->eventdt ) );
201
- $records = $entry->totalrecd;
202
- $level = $entry->consentlevel;
203
-
204
- $i = array_search( $time, $data['labels'] );
205
-
206
- if ( $i )
207
- $data['datasets'][$level - 1]['data'][$i] = $records;
208
- }
209
-
210
- $chartdata['consent-activity']['data'] = $data;
211
- }
212
-
213
- // echo '<pre>'; print_r( $chartdata ); echo '</pre>'; exit;
214
-
215
- wp_localize_script(
216
- 'cn-admin-dashboard',
217
- 'cnDashboardArgs',
218
- [
219
- 'ajaxURL' => admin_url( 'admin-ajax.php' ),
220
- 'nonce' => wp_create_nonce( 'cn-dashboard-widget' ),
221
- 'nonceUser' => wp_create_nonce( 'cn-dashboard-user-options' ),
222
- 'charts' => $chartdata
223
- ]
224
- );
225
- }
226
-
227
- /**
228
- * Render dashboard widget.
229
- *
230
- * @return void
231
- */
232
- public function dashboard_widget() {
233
- $html = '';
234
-
235
- // Compliance active, display chart
236
- if ( Cookie_Notice()->get_status() == 'active' ) {
237
- // get user options
238
- $user_options = get_user_meta( get_current_user_id(), 'pvc_dashboard', true );
239
-
240
- // empty options?
241
- if ( empty( $user_options ) || ! is_array( $user_options ) )
242
- $user_options = [];
243
-
244
- // sanitize options
245
- $user_options = map_deep( $user_options, 'sanitize_text_field' );
246
-
247
- // get menu items
248
- $menu_items = ! empty( $user_options['menu_items'] ) ? $user_options['menu_items'] : [];
249
-
250
- $items = [
251
- [
252
- 'id' => 'visits',
253
- 'title' => __( 'Traffic Overview', 'cookie-notice' ),
254
- 'description' => __( 'Displays the general visits information for your domain.', 'cookie-notice' )
255
- ],
256
- [
257
- 'id' => 'consent-activity',
258
- 'title' => __( 'Consent Activity', 'cookie-notice' ),
259
- 'description' => __( 'Displays the chart of the domain consent activity in the last 30 days.', 'cookie-notice' )
260
- ],
261
- ];
262
-
263
- $html = '
264
- <div id="cn-dashboard-accordion" class="cn-accordion">';
265
-
266
- foreach ( $items as $item ) {
267
- $html .= $this->widget_item( $item, $menu_items );
268
- }
269
-
270
- $html .= '
271
- </div>';
272
- // Compliance inactive, display image
273
- } else {
274
- $html = '
275
- <div id="cn-dashboard-accordion" class="cn-accordion cn-widget-block">
276
- <img src="' . plugins_url( '../img/cookie-compliance-widget.png', __FILE__ ) . '" alt="Cookie Compliance widget" />
277
- <div id="cn-dashboard-upgrade">
278
- <div id="cn-dashboard-modal">
279
- <h2>' . __( 'View consent activity inside WordPress Dashboard', 'cookie-notice' ) . '</h2>
280
- <p>' . __( 'Display information about the visits.', 'cookie-notice' ) . '</p>
281
- <p>' . __( 'Get Consent logs data for the last 30 days.', 'cookie-notice' ) . '</p>
282
- <p>' . __( 'Enable consent purpose categories, automatic cookie blocking and more.', 'cookie-notice' ) . '</p>
283
- <p><a href="' . admin_url( 'admin.php' ) . '?page=cookie-notice&welcome=1' . '" class="button button-primary button-hero cn-button">' . __( 'Upgrade to Cookie Compliance', 'cookie-notice' ) . '</a></p>
284
- </div>
285
- </div>
286
- </div>';
287
- }
288
-
289
-
290
- echo $html;
291
- }
292
-
293
- /**
294
- * Generate dashboard widget item HTML.
295
- *
296
- * @param array $item
297
- * @param array $menu_items
298
- * @return string
299
- */
300
- public function widget_item( $item, $menu_items ) {
301
- // allows a list of HTML Entities such as
302
- $allowed_html = wp_kses_allowed_html( 'post' );
303
- $allowed_html['canvas'] = [
304
- 'id' => [],
305
- 'height' => []
306
- ];
307
-
308
- $html = '
309
- <div id="cn-' . esc_attr( $item['id'] ) . '" class="cn-accordion-item' . ( in_array( $item['id'], $menu_items, true ) ? ' cn-collapsed' : '' ) . '">
310
- <div class="cn-accordion-header">
311
- <div class="cn-accordion-toggle"><span class="cn-accordion-title">' . esc_html( $item['title'] ) . '</span><span class="cn-tooltip" aria-label="' . esc_html( $item['description'] ) . '" data-microtip-position="top" data-microtip-size="large" role="tooltip"><span class="cn-tooltip-icon"></span></span></div>
312
- </div>
313
- <div class="cn-accordion-content">
314
- <div class="cn-dashboard-container">
315
- <div class="cn-data-container">
316
- ' . wp_kses( $this->widget_item_content( $item['id'] ), $allowed_html ) . '
317
- <span class="spinner"></span>
318
- </div>
319
- </div>
320
- </div>
321
- </div>';
322
-
323
- return $html;
324
- }
325
-
326
- /**
327
- * Generate dashboard widget item HTML.
328
- *
329
- * @param array $item
330
- * @param array $menu_items
331
- * @return string
332
- */
333
- public function widget_item_content( $item ) {
334
- $html = '';
335
-
336
- // get analytics data options
337
- $analytics = get_option( 'cookie_notice_app_analytics' );
338
-
339
- $date_format = get_option( 'date_format' );
340
-
341
- // thirty days data
342
- $thirty_days_usage = array(
343
- 'visits' => ! empty( $analytics['thirtyDaysUsage']->visits ) ? (int) $analytics['thirtyDaysUsage']->visits : 0,
344
- 'visits_updated' => ! empty( $analytics['thirtyDaysUsage']->fetchTime ) ? date_i18n( $date_format, strtotime( $analytics['thirtyDaysUsage']->fetchTime ) ) : date_i18n( $date_format, strtotime( current_time( 'mysql' ) ) ),
345
- 'consents' => 0,
346
- 'consents_updated' => ! empty( $analytics['lastUpdated'] ) ? date_i18n( $date_format, strtotime( $analytics['lastUpdated'] ) ) : date_i18n( $date_format, strtotime( current_time( 'mysql' ) ) )
347
- );
348
-
349
- if ( ! empty( $analytics['consentActivities'] ) ) {
350
- foreach ( $analytics['consentActivities'] as $index => $entry ) {
351
- $thirty_days_usage['consents'] += (int) $entry->totalrecd;
352
- }
353
- }
354
-
355
- // cycle usage data
356
- $cycle_usage = array(
357
- 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
358
- 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0,
359
- 'days_to_go' => ! empty( $analytics['cycleUsage']->daysToGo ) ? (int) $analytics['cycleUsage']->daysToGo : 0,
360
- 'start_date' => ! empty( $analytics['cycleUsage']->startDate ) ? date_i18n( $date_format, strtotime( $analytics['cycleUsage']->startDate ) ) : '',
361
- 'end_date' => ! empty( $analytics['cycleUsage']->endDate ) ? date_i18n( $date_format, strtotime( $analytics['cycleUsage']->endDate ) ) : ''
362
- );
363
-
364
- // available visits, -1 for no pro plans
365
- $cycle_usage['visits_available'] = $cycle_usage['threshold'] ? $cycle_usage['threshold'] - $cycle_usage['visits'] : -1;
366
- $cycle_usage['threshold_used'] = $cycle_usage['threshold'] ? ( $cycle_usage['visits'] / $cycle_usage['threshold'] ) * 100 : 0;
367
- $cycle_usage['threshold_used'] = $cycle_usage['threshold_used'] > 100 ? 100 : $cycle_usage['threshold_used'];
368
-
369
- switch ($item) {
370
- case 'visits' :
371
- $html .= '
372
- <div id="cn-dashboard-' . $item . '">
373
- <div id="cn-' . $item . '-infobox-traffic-overview" class="cn-infobox-container">
374
- <div id="cn-' . $item . '-infobox-visits" class="cn-infobox">
375
- <div class="cn-infobox-title">' . __( 'Total Visits', 'cookie-notice' ) . '</div>
376
- <div class="cn-infobox-number">' . number_format_i18n( $thirty_days_usage['visits'], 0 ) . '</div>
377
- <div class="cn-infobox-subtitle">' . __( 'Last 30 days', 'cookie-notice' ) . '</div>
378
- </div>
379
- <div id="cn-' . $item . '-infobox-consents" class="cn-infobox">
380
- <div class="cn-infobox-title">' . __( 'Consent Logs', 'cookie-notice' ) . '</div>
381
- <div class="cn-infobox-number">' . number_format_i18n( $thirty_days_usage['consents'], 0 ) . '</div>
382
- <div class="cn-infobox-subtitle">' . sprintf( __( 'Updated %s', 'cookie-notice' ), $thirty_days_usage['consents_updated'] ) . '</div>
383
- </div>
384
- </div>';
385
-
386
- if ( $cycle_usage['threshold'] ) {
387
- $usage_class = 'success';
388
-
389
- // warning usage color
390
- if ( $cycle_usage['threshold_used'] > 80 && $cycle_usage['threshold_used'] < 100 ) {
391
- $usage_class = 'warning';
392
- // danger usage color
393
- } elseif ( $cycle_usage['threshold_used'] == 100 ) {
394
- $usage_class = 'danger';
395
- }
396
-
397
- $html .= '
398
- <div id="cn-' . $item . '-infobox-traffic-usage" class="cn-infobox-container">
399
- <div id="cn-' . $item . '-infobox-limits" class="cn-infobox">
400
- <div class="cn-infobox-title">' . __( 'Traffic Usage', 'cookie-notice' ) . '</div>
401
- <div class="cn-infobox-number cn-text-' . $usage_class . '">' . number_format_i18n( $cycle_usage['threshold_used'], 1 ) . ' %</div>
402
- <div class="cn-infobox-subtitle">
403
- <p>' . sprintf( __( 'Visits usage: %1$s / %2$s', 'cookie-notice' ), $cycle_usage['visits'], $cycle_usage['threshold'] ) . '</p>
404
- <p>' . sprintf( __( 'Cycle started: %s', 'cookie-notice' ), date( $date_format, strtotime( $cycle_usage['start_date'] ) ) ) . '</p>
405
- <p>' . sprintf( __( 'Days to go: %s', 'cookie-notice' ), $cycle_usage['days_to_go'] ) . '</p>
406
- </div>
407
- </div>
408
- <div id="cn-' . $item . '-chart-limits" class="cn-infobox cn-chart-container">
409
- <canvas id="cn-usage-chart" style="height: 100px;"></canvas>
410
- </div>';
411
-
412
- /*
413
- <div id="cn-' . $item . '-traffic-notice" class="cn-infobox-notice cn-traffic-' . $usage_class . '">
414
- <p><b>' . __( 'Your domain has exceeded 90% of the usage limit.', 'cookie-notice' ) . '</b></p>
415
- <p>' . sprintf(__( 'The banner will still display properly and consent record will be set in the browser. However the Autoblocking will be disabled and Consent Records will not be stored in the application until the current visits cycle resets (in %s days).', 'cookie-notice' ), $cycle_usage['days_to_go'] ) . '</p>
416
- </div>
417
- *
418
- */
419
-
420
- $html .= '
421
- </div>';
422
- }
423
-
424
- $html .= '
425
- </div>
426
- ';
427
-
428
- break;
429
-
430
- case 'consent-activity' :
431
- $html .= '
432
- <div id="cn-dashboard-' . $item . '">
433
- <div id="cn-' . $item . '-chart-container cn-chart-container">
434
- <canvas id="cn-' . $item . '-chart" style="height: 300px;"></canvas>
435
- </div>
436
- </div>';
437
- break;
438
-
439
- default :
440
- break;
441
- }
442
-
443
- return $html;
444
- }
445
-
446
- /**
447
- * Add site test.
448
- *
449
- * @param type $tests
450
- * @return array
451
- */
452
- public function add_tests( $tests ) {
453
- $tests['direct']['cookie_compliance_status'] = array(
454
- 'label' => __( 'Cookie Compliance Status', 'cookie-notice' ),
455
- 'test' => array( $this, 'test_cookie_compliance' ),
456
- );
457
-
458
- return $tests;
459
- }
460
-
461
- /**
462
- * Test for Cookie Compliance.
463
- *
464
- * @return boolean
465
- */
466
- public function test_cookie_compliance() {
467
-
468
- if ( Cookie_Notice()->get_status() !== 'active' ) {
469
- $setup_link = add_query_arg( array(
470
- 'page' => 'cookie-notice',
471
- 'welcome' => 1
472
- ), admin_url( 'admin.php' ) );
473
-
474
- return array(
475
- 'label' => __( 'Your site does not have Cookie Compliance', 'cookie-notice' ),
476
- 'status' => 'critical',
477
- 'badge' => array(
478
- 'label' => __( 'Cookie Notice', 'cookie-notice' ),
479
- 'color' => 'blue',
480
- ),
481
- 'description' => __( "Run Compliance Check to determine your site's compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws.", 'cookie-notice' ),
482
- 'actions' => sprintf(
483
- '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></p>',
484
- $setup_link,
485
- __( 'Run Compliance Check', 'cookie-notice' )
486
- ),
487
- 'test' => 'cookie_compliance_status',
488
- );
489
- }
490
- }
491
-
492
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) )
5
+ exit;
6
+
7
+ /**
8
+ * Cookie_Notice_Dashboard class.
9
+ *
10
+ * @class Cookie_Notice_Dashboard
11
+ */
12
+ class Cookie_Notice_Dashboard {
13
+
14
+ /**
15
+ * Class constructor.
16
+ *
17
+ * @return void
18
+ */
19
+ public function __construct() {
20
+ // actions
21
+ add_action( 'wp_dashboard_setup', [ $this, 'wp_dashboard_setup' ], 11 );
22
+ add_action( 'wp_network_dashboard_setup', [ $this, 'wp_dashboard_setup' ], 11 );
23
+ add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts_styles' ] );
24
+
25
+ // site status
26
+ add_filter( 'site_status_tests', [ $this, 'add_tests' ] );
27
+ }
28
+
29
+ /**
30
+ * Initialize widget.
31
+ *
32
+ * @global array $wp_meta_boxes
33
+ *
34
+ * @return void
35
+ */
36
+ public function wp_dashboard_setup() {
37
+ // filter user_can_see_stats
38
+ if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
39
+ return;
40
+
41
+ // get main instance
42
+ $cn = Cookie_Notice();
43
+
44
+ // check when to hide widget
45
+ if ( is_multisite() ) {
46
+ // site dashboard
47
+ if ( current_action() === 'wp_dashboard_setup' && $cn->is_plugin_network_active() && $cn->network_options['global_override'] )
48
+ return;
49
+
50
+ // network dashboard
51
+ if ( current_action() === 'wp_network_dashboard_setup' ) {
52
+ if ( $cn->is_plugin_network_active() ) {
53
+ if ( ! $cn->network_options['global_override'] )
54
+ return;
55
+ } else
56
+ return;
57
+ }
58
+ }
59
+
60
+ // check is it network admin
61
+ if ( $cn->is_network_admin() )
62
+ $dashboard_key = 'dashboard-network';
63
+ else
64
+ $dashboard_key = 'dashboard';
65
+
66
+ global $wp_meta_boxes;
67
+
68
+ // set widget key
69
+ $widget_key = 'cn_dashboard_stats';
70
+
71
+ // add dashboard chart widget
72
+ wp_add_dashboard_widget( $widget_key, __( 'Cookie Compliance', 'cookie-notice' ), [ $this, 'dashboard_widget' ] );
73
+
74
+ // get widgets
75
+ $normal_dashboard = $wp_meta_boxes[$dashboard_key]['normal']['core'];
76
+
77
+ // attempt to place the widget at the top
78
+ $widget_instance = [
79
+ $widget_key => $normal_dashboard[ $widget_key ]
80
+ ];
81
+
82
+ // remove new widget
83
+ unset( $normal_dashboard[ $widget_key ] );
84
+
85
+ // merge widgets
86
+ $sorted_dashboard = array_merge( $widget_instance, $normal_dashboard );
87
+
88
+ // update widgets
89
+ $wp_meta_boxes[$dashboard_key]['normal']['core'] = $sorted_dashboard;
90
+ }
91
+
92
+ /**
93
+ * Enqueue admin scripts and styles.
94
+ *
95
+ * @param string $pagenow
96
+ * @return void
97
+ */
98
+ public function admin_scripts_styles( $pagenow ) {
99
+ if ( $pagenow !== 'index.php' )
100
+ return;
101
+
102
+ // filter user_can_see_stats
103
+ if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
104
+ return;
105
+
106
+ // get main instance
107
+ $cn = Cookie_Notice();
108
+
109
+ $date_format = get_option( 'date_format' );
110
+
111
+ if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] )
112
+ $analytics = get_site_option( 'cookie_notice_app_analytics' );
113
+ else
114
+ $analytics = get_option( 'cookie_notice_app_analytics' );
115
+
116
+ // styles
117
+ wp_enqueue_style( 'cn-admin-dashboard', plugins_url( '../css/admin-dashboard.css', __FILE__ ), [], $cn->defaults['version'] );
118
+ wp_enqueue_style( 'cn-microtip', plugins_url( '../assets/microtip/microtip.min.css', __FILE__ ), [], $cn->defaults['version'] );
119
+
120
+ // bail if compliance is not active
121
+ if ( $cn->get_status() !== 'active' )
122
+ return;
123
+
124
+ // scripts
125
+ wp_enqueue_script( 'cn-admin-chartjs', plugins_url( '../assets/chartjs/chart.min.js', __FILE__ ), [ 'jquery' ], $cn->defaults['version'], true );
126
+ wp_enqueue_script( 'cn-admin-dashboard', plugins_url( '../js/admin-dashboard.js', __FILE__ ), [ 'jquery', 'cn-admin-chartjs' ], $cn->defaults['version'], true );
127
+
128
+ // cycle usage data
129
+ $cycle_usage = [
130
+ 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
131
+ 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0
132
+ ];
133
+
134
+ // available visits, -1 for no pro plans
135
+ $cycle_usage['visits_available'] = $cycle_usage['threshold'] ? $cycle_usage['threshold'] - $cycle_usage['visits'] : -1;
136
+ $cycle_usage['threshold_used'] = $cycle_usage['threshold'] ? ( $cycle_usage['visits'] / $cycle_usage['threshold'] ) * 100 : 0;
137
+ $cycle_usage['threshold_used'] = $cycle_usage['threshold_used'] > 100 ? 100 : $cycle_usage['threshold_used'];
138
+
139
+ $chartdata = [
140
+ 'usage' => [
141
+ 'type' => 'doughnut',
142
+ 'data' => [
143
+ 'labels' => [
144
+ _x( 'Used', 'threshold limit', 'cookie-notice' ),
145
+ _x( 'Free', 'threshold limit', 'cookie-notice' )
146
+ ],
147
+ 'datasets' => [
148
+ [
149
+ 'data' => [ $cycle_usage['visits'], $cycle_usage['visits_available'] ],
150
+ // 'borderColor' => 'rgb(255, 255, 255)',
151
+ 'backgroundColor' => [
152
+ 'rgb(32, 193, 158)',
153
+ 'rgb(235, 233, 235)'
154
+ ]
155
+ ]
156
+ ]
157
+ ]
158
+ ],
159
+ 'consent-activity' => [
160
+ 'type' => 'line'
161
+ ]
162
+ ];
163
+
164
+ // warning usage color
165
+ if ( $cycle_usage['threshold_used'] > 80 && $cycle_usage['threshold_used'] < 100 )
166
+ $chartdata['usage']['data']['datasets'][0]['backgroundColor'][0] = 'rgb(255, 193, 7)';
167
+ // danger usage color
168
+ elseif ( $cycle_usage['threshold_used'] == 100 )
169
+ $chartdata['usage']['data']['datasets'][0]['backgroundColor'][0] = 'rgb(220, 53, 69)';
170
+
171
+ $data = [
172
+ 'labels' => [],
173
+ 'datasets' => [
174
+ 0 => [
175
+ 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 1 ),
176
+ 'data' => [],
177
+ 'fill' => true,
178
+ 'backgroundColor' => 'rgba(196, 196, 196, 0.3)',
179
+ 'borderColor' => 'rgba(196, 196, 196, 1)',
180
+ 'borderWidth' => 1.2,
181
+ 'borderDash' => [],
182
+ 'pointBorderColor' => 'rgba(196, 196, 196, 1)',
183
+ 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
184
+ 'pointBorderWidth' => 1.2
185
+ ],
186
+ 1 => [
187
+ 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 2 ),
188
+ 'data' => [],
189
+ 'fill' => true,
190
+ 'backgroundColor' => 'rgba(213, 181, 101, 0.3)',
191
+ 'borderColor' => 'rgba(213, 181, 101, 1)',
192
+ 'borderWidth' => 1.2,
193
+ 'borderDash' => [],
194
+ 'pointBorderColor' => 'rgba(213, 181, 101, 1)',
195
+ 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
196
+ 'pointBorderWidth' => 1.2
197
+ ],
198
+ 2 => [
199
+ 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 3 ),
200
+ 'data' => [],
201
+ 'fill' => true,
202
+ 'backgroundColor' => 'rgba(152, 145, 177, 0.3)',
203
+ 'borderColor' => 'rgba(152, 145, 177, 1)',
204
+ 'borderWidth' => 1.2,
205
+ 'borderDash' => [],
206
+ 'pointBorderColor' => 'rgba(152, 145, 177, 1)',
207
+ 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
208
+ 'pointBorderWidth' => 1.2
209
+ ]
210
+ ]
211
+ ];
212
+
213
+ // generate chart days
214
+ $chart_date_format = 'j/m';
215
+
216
+ for ( $i = 30; $i >= 0; $i-- ) {
217
+ // set label
218
+ $data['labels'][] = date( $chart_date_format, strtotime( '-'. $i .' days' ) );
219
+
220
+ // reset datasets
221
+ $data['datasets'][0]['data'][] = 0;
222
+ $data['datasets'][1]['data'][] = 0;
223
+ $data['datasets'][2]['data'][] = 0;
224
+ }
225
+
226
+ if ( ! empty( $analytics['consentActivities'] ) && is_array( $analytics['consentActivities'] ) ) {
227
+ // set consent records in charts days
228
+ foreach ( $analytics['consentActivities'] as $index => $entry ) {
229
+ $time = date_i18n( $chart_date_format, strtotime( $entry->eventdt ) );
230
+ $records = $entry->totalrecd;
231
+ $level = $entry->consentlevel;
232
+
233
+ $i = array_search( $time, $data['labels'] );
234
+
235
+ if ( $i )
236
+ $data['datasets'][$level - 1]['data'][$i] = $records;
237
+ }
238
+ }
239
+
240
+ $chartdata['consent-activity']['data'] = $data;
241
+
242
+ wp_localize_script(
243
+ 'cn-admin-dashboard',
244
+ 'cnDashboardArgs',
245
+ [
246
+ 'ajaxURL' => admin_url( 'admin-ajax.php' ),
247
+ 'nonce' => wp_create_nonce( 'cn-dashboard-widget' ),
248
+ 'nonceUser' => wp_create_nonce( 'cn-dashboard-user-options' ),
249
+ 'charts' => $chartdata
250
+ ]
251
+ );
252
+ }
253
+
254
+ /**
255
+ * Render dashboard widget.
256
+ *
257
+ * @return void
258
+ */
259
+ public function dashboard_widget() {
260
+ // get main instance
261
+ $cn = Cookie_Notice();
262
+
263
+ if ( $cn->is_network_admin() )
264
+ $upgrade_url = network_admin_url( 'admin.php?page=cookie-notice&welcome=1' );
265
+ else
266
+ $upgrade_url = admin_url( 'admin.php?page=cookie-notice&welcome=1' );
267
+
268
+ $html = '';
269
+
270
+ // compliance active, display chart
271
+ if ( $cn->get_status() === 'active' ) {
272
+ // get user options
273
+ $user_options = get_user_meta( get_current_user_id(), 'pvc_dashboard', true );
274
+
275
+ // empty options?
276
+ if ( empty( $user_options ) || ! is_array( $user_options ) )
277
+ $user_options = [];
278
+
279
+ // sanitize options
280
+ $user_options = map_deep( $user_options, 'sanitize_text_field' );
281
+
282
+ // get menu items
283
+ $menu_items = ! empty( $user_options['menu_items'] ) ? $user_options['menu_items'] : [];
284
+
285
+ $items = [
286
+ [
287
+ 'id' => 'visits',
288
+ 'title' => __( 'Traffic Overview', 'cookie-notice' ),
289
+ 'description' => __( 'Displays the general visits information for your domain.', 'cookie-notice' )
290
+ ],
291
+ [
292
+ 'id' => 'consent-activity',
293
+ 'title' => __( 'Consent Activity', 'cookie-notice' ),
294
+ 'description' => __( 'Displays the chart of the domain consent activity in the last 30 days.', 'cookie-notice' )
295
+ ]
296
+ ];
297
+
298
+ $html .= '
299
+ <div id="cn-dashboard-accordion" class="cn-accordion">';
300
+
301
+ foreach ( $items as $item ) {
302
+ $html .= $this->widget_item( $item, $menu_items );
303
+ }
304
+
305
+ $html .= '
306
+ </div>';
307
+ // compliance inactive, display image
308
+ } else {
309
+ $html .= '
310
+ <div id="cn-dashboard-accordion" class="cn-accordion cn-widget-block">
311
+ <img src="' . plugins_url( '../img/cookie-compliance-widget.png', __FILE__ ) . '" alt="Cookie Compliance widget" />
312
+ <div id="cn-dashboard-upgrade">
313
+ <div id="cn-dashboard-modal">
314
+ <h2>' . __( 'View consent activity inside WordPress Dashboard', 'cookie-notice' ) . '</h2>
315
+ <p>' . __( 'Display information about the visits.', 'cookie-notice' ) . '</p>
316
+ <p>' . __( 'Get Consent logs data for the last 30 days.', 'cookie-notice' ) . '</p>
317
+ <p>' . __( 'Enable consent purpose categories, automatic cookie blocking and more.', 'cookie-notice' ) . '</p>
318
+ <p><a href="' . $upgrade_url . '" class="button button-primary button-hero cn-button">' . __( 'Upgrade to Cookie Compliance', 'cookie-notice' ) . '</a></p>
319
+ </div>
320
+ </div>
321
+ </div>';
322
+ }
323
+
324
+ echo $html;
325
+ }
326
+
327
+ /**
328
+ * Generate dashboard widget item HTML.
329
+ *
330
+ * @param array $item
331
+ * @param array $menu_items
332
+ * @return string
333
+ */
334
+ public function widget_item( $item, $menu_items ) {
335
+ // allows a list of html entities such as
336
+ $allowed_html = wp_kses_allowed_html( 'post' );
337
+ $allowed_html['canvas'] = [
338
+ 'id' => [],
339
+ 'height' => []
340
+ ];
341
+
342
+ return '
343
+ <div id="cn-' . esc_attr( $item['id'] ) . '" class="cn-accordion-item' . ( in_array( $item['id'], $menu_items, true ) ? ' cn-collapsed' : '' ) . '">
344
+ <div class="cn-accordion-header">
345
+ <div class="cn-accordion-toggle"><span class="cn-accordion-title">' . esc_html( $item['title'] ) . '</span><span class="cn-tooltip" aria-label="' . esc_html( $item['description'] ) . '" data-microtip-position="top" data-microtip-size="large" role="tooltip"><span class="cn-tooltip-icon"></span></span></div>
346
+ </div>
347
+ <div class="cn-accordion-content">
348
+ <div class="cn-dashboard-container">
349
+ <div class="cn-data-container">
350
+ ' . wp_kses( $this->widget_item_content( $item['id'] ), $allowed_html ) . '
351
+ <span class="spinner"></span>
352
+ </div>
353
+ </div>
354
+ </div>
355
+ </div>';
356
+ }
357
+
358
+ /**
359
+ * Generate dashboard widget item content HTML.
360
+ *
361
+ * @param array $item
362
+ * @return string
363
+ */
364
+ public function widget_item_content( $item ) {
365
+ $html = '';
366
+
367
+ switch ( $item ) {
368
+ case 'visits':
369
+ // get main instance
370
+ $cn = Cookie_Notice();
371
+
372
+ $date_format = get_option( 'date_format' );
373
+
374
+ // get analytics data options
375
+ if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] )
376
+ $analytics = get_site_option( 'cookie_notice_app_analytics' );
377
+ else
378
+ $analytics = get_option( 'cookie_notice_app_analytics' );
379
+
380
+ // thirty days data
381
+ $thirty_days_usage = [
382
+ 'visits' => ! empty( $analytics['thirtyDaysUsage']->visits ) ? (int) $analytics['thirtyDaysUsage']->visits : 0,
383
+ // 'visits_updated' => ! empty( $analytics['thirtyDaysUsage']->fetchTime ) ? date_create_from_format( 'Y-m-d H:i:s', $analytics['thirtyDaysUsage']->fetchTime ) : date_create_from_format( 'Y-m-d H:i:s', current_time( 'mysql', true ) ),
384
+ 'consents' => 0,
385
+ 'consents_updated' => ! empty( $analytics['lastUpdated'] ) ? date_create_from_format( 'Y-m-d H:i:s', $analytics['lastUpdated'] ) : date_create_from_format( 'Y-m-d H:i:s', current_time( 'mysql', true ) )
386
+ ];
387
+
388
+ if ( ! empty( $analytics['consentActivities'] ) ) {
389
+ foreach ( $analytics['consentActivities'] as $index => $entry ) {
390
+ $thirty_days_usage['consents'] += (int) $entry->totalrecd;
391
+ }
392
+ }
393
+
394
+ // cycle usage data
395
+ $cycle_usage = [
396
+ 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
397
+ 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0,
398
+ 'days_to_go' => ! empty( $analytics['cycleUsage']->daysToGo ) ? (int) $analytics['cycleUsage']->daysToGo : 0,
399
+ 'start_date' => ! empty( $analytics['cycleUsage']->startDate ) ? date_create_from_format( '!Y-m-d', $analytics['cycleUsage']->startDate ) : '',
400
+ // 'end_date' => ! empty( $analytics['cycleUsage']->endDate ) ? date_create_from_format( '!Y-m-d', $analytics['cycleUsage']->endDate ) : ''
401
+ ];
402
+
403
+ // set current timezone
404
+ $current_timezone = new DateTimeZone( $cn->timezone_string() );
405
+
406
+ // update dates
407
+ // $thirty_days_usage['visits_updated']->setTimezone( $current_timezone );
408
+ $thirty_days_usage['consents_updated']->setTimezone( $current_timezone );
409
+
410
+ // available visits, -1 for no pro plans
411
+ $cycle_usage['visits_available'] = $cycle_usage['threshold'] ? $cycle_usage['threshold'] - $cycle_usage['visits'] : -1;
412
+ $cycle_usage['threshold_used'] = $cycle_usage['threshold'] ? ( $cycle_usage['visits'] / $cycle_usage['threshold'] ) * 100 : 0;
413
+ $cycle_usage['threshold_used'] = $cycle_usage['threshold_used'] > 100 ? 100 : $cycle_usage['threshold_used'];
414
+
415
+ $html .= '
416
+ <div id="cn-dashboard-' . $item . '">
417
+ <div id="cn-' . $item . '-infobox-traffic-overview" class="cn-infobox-container">
418
+ <div id="cn-' . $item . '-infobox-visits" class="cn-infobox">
419
+ <div class="cn-infobox-title">' . __( 'Total Visits', 'cookie-notice' ) . '</div>
420
+ <div class="cn-infobox-number">' . number_format_i18n( $thirty_days_usage['visits'], 0 ) . '</div>
421
+ <div class="cn-infobox-subtitle">' . __( 'Last 30 days', 'cookie-notice' ) . '</div>
422
+ </div>
423
+ <div id="cn-' . $item . '-infobox-consents" class="cn-infobox">
424
+ <div class="cn-infobox-title">' . __( 'Consent Logs', 'cookie-notice' ) . '</div>
425
+ <div class="cn-infobox-number">' . number_format_i18n( $thirty_days_usage['consents'], 0 ) . '</div>
426
+ <div class="cn-infobox-subtitle">' . sprintf( __( 'Updated %s', 'cookie-notice' ), date_i18n( $date_format, $thirty_days_usage['consents_updated']->getTimestamp() ) ) . '</div>
427
+ </div>
428
+ </div>';
429
+
430
+ if ( $cycle_usage['threshold'] ) {
431
+ $usage_class = 'success';
432
+
433
+ // warning usage color
434
+ if ( $cycle_usage['threshold_used'] > 80 && $cycle_usage['threshold_used'] < 100 )
435
+ $usage_class = 'warning';
436
+ // danger usage color
437
+ elseif ( $cycle_usage['threshold_used'] == 100 )
438
+ $usage_class = 'danger';
439
+
440
+ $html .= '
441
+ <div id="cn-' . $item . '-infobox-traffic-usage" class="cn-infobox-container">
442
+ <div id="cn-' . $item . '-infobox-limits" class="cn-infobox">
443
+ <div class="cn-infobox-title">' . __( 'Traffic Usage', 'cookie-notice' ) . '</div>
444
+ <div class="cn-infobox-number cn-text-' . $usage_class . '">' . number_format_i18n( $cycle_usage['threshold_used'], 1 ) . ' %</div>
445
+ <div class="cn-infobox-subtitle">
446
+ <p>' . sprintf( __( 'Visits usage: %1$s / %2$s', 'cookie-notice' ), $cycle_usage['visits'], $cycle_usage['threshold'] ) . '</p>
447
+ <p>' . sprintf( __( 'Cycle started: %s', 'cookie-notice' ), date_i18n( $date_format, $cycle_usage['start_date']->getTimestamp() ) ) . '</p>
448
+ <p>' . sprintf( __( 'Days to go: %s', 'cookie-notice' ), $cycle_usage['days_to_go'] ) . '</p>
449
+ </div>
450
+ </div>
451
+ <div id="cn-' . $item . '-chart-limits" class="cn-infobox cn-chart-container">
452
+ <canvas id="cn-usage-chart" style="height: 100px;"></canvas>
453
+ </div>';
454
+
455
+ /*
456
+ <div id="cn-' . $item . '-traffic-notice" class="cn-infobox-notice cn-traffic-' . $usage_class . '">
457
+ <p><b>' . __( 'Your domain has exceeded 90% of the usage limit.', 'cookie-notice' ) . '</b></p>
458
+ <p>' . sprintf(__( 'The banner will still display properly and consent record will be set in the browser. However the Autoblocking will be disabled and Consent Records will not be stored in the application until the current visits cycle resets (in %s days).', 'cookie-notice' ), $cycle_usage['days_to_go'] ) . '</p>
459
+ </div>
460
+ */
461
+
462
+ $html .= '
463
+ </div>';
464
+ }
465
+
466
+ $html .= '
467
+ </div>';
468
+ break;
469
+
470
+ case 'consent-activity':
471
+ $html .= '
472
+ <div id="cn-dashboard-' . $item . '">
473
+ <div id="cn-' . $item . '-chart-container cn-chart-container">
474
+ <canvas id="cn-' . $item . '-chart" style="height: 300px;"></canvas>
475
+ </div>
476
+ </div>';
477
+ break;
478
+ }
479
+
480
+ return $html;
481
+ }
482
+
483
+ /**
484
+ * Add site test.
485
+ *
486
+ * @param array $tests
487
+ * @return array
488
+ */
489
+ public function add_tests( $tests ) {
490
+ $tests['direct']['cookie_compliance_status'] = [
491
+ 'label' => __( 'Cookie Compliance Status', 'cookie-notice' ),
492
+ 'test' => [ $this, 'test_cookie_compliance' ]
493
+ ];
494
+
495
+ return $tests;
496
+ }
497
+
498
+ /**
499
+ * Test for Cookie Compliance.
500
+ *
501
+ * @return array|void
502
+ */
503
+ public function test_cookie_compliance() {
504
+ if ( Cookie_Notice()->get_status() !== 'active' ) {
505
+ $setup_link = add_query_arg( [
506
+ 'page' => 'cookie-notice',
507
+ 'welcome' => 1
508
+ ], admin_url( 'admin.php' ) );
509
+
510
+ return [
511
+ 'label' => __( 'Your site does not have Cookie Compliance', 'cookie-notice' ),
512
+ 'status' => 'critical',
513
+ 'badge' => [
514
+ 'label' => __( 'Cookie Notice', 'cookie-notice' ),
515
+ 'color' => 'blue'
516
+ ],
517
+ 'description' => __( "Run Compliance Check to determine your site's compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws.", 'cookie-notice' ),
518
+ 'actions' => sprintf( '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></p>', $setup_link, __( 'Run Compliance Check', 'cookie-notice' ) ),
519
+ 'test' => 'cookie_compliance_status'
520
+ ];
521
+ }
522
+ }
523
+ }
includes/frontend.php CHANGED
@@ -5,24 +5,30 @@ if ( ! defined( 'ABSPATH' ) )
5
 
6
  /**
7
  * Cookie_Notice_Frontend class.
8
- *
9
  * @class Cookie_Notice_Frontend
10
  */
11
  class Cookie_Notice_Frontend {
 
12
  private $is_bot = false;
13
  private $hide_banner = false;
14
-
15
- // api urls
16
- private $widget_url = '//cdn.hu-manity.co/hu-banner.min.js';
17
- private $app_url = 'https://app.hu-manity.co';
18
 
 
 
 
 
 
19
  public function __construct() {
20
  // actions
21
  add_action( 'init', array( $this, 'init' ) );
22
  }
23
 
24
  /**
25
- * Init frontend.
 
 
 
 
26
  */
27
  public function init() {
28
  // purge cache
@@ -34,7 +40,7 @@ class Cookie_Notice_Frontend {
34
 
35
  // is it a bot?
36
  $this->is_bot = Cookie_Notice()->bot_detect->is_crawler();
37
-
38
  // is user logged in and hiding the banner is enabled
39
  $this->hide_banner = is_user_logged_in() && Cookie_Notice()->options['general']['hide_banner'] === true;
40
 
@@ -63,9 +69,11 @@ class Cookie_Notice_Frontend {
63
 
64
  /**
65
  * Add CORS header for API requests and purge cache.
 
 
66
  */
67
  public function add_compliance_http_header() {
68
- header( "Access-Control-Allow-Origin: $this->app_url" );
69
  header( 'Access-Control-Allow-Methods: GET' );
70
  }
71
 
@@ -75,86 +83,120 @@ class Cookie_Notice_Frontend {
75
  * @return void
76
  */
77
  public function add_cookie_compliance() {
 
 
 
78
  // get site language
79
  $locale = get_locale();
80
  $locale_code = explode( '_', $locale );
81
 
82
  // exceptions, norwegian
83
- if ( in_array( $locale_code, array( 'nb', 'nn' ) ) )
84
  $locale_code = 'no';
85
 
86
- $options = apply_filters( 'cn_cookie_compliance_args', array(
87
- 'appID' => Cookie_Notice()->options['general']['app_id'],
88
- 'currentLanguage' => $locale_code[0],
89
- 'blocking' => (bool) ( ! is_user_logged_in() ? Cookie_Notice()->options['general']['app_blocking'] : false )
90
- ) );
91
-
92
- if ( Cookie_Notice()->options['general']['debug_mode'] ) {
 
 
 
 
93
  $options['debugMode'] = true;
94
- }
95
-
96
  // message output
97
  $output = '
98
  <!-- Hu Banner -->
99
  <script type="text/javascript">
100
  var huOptions = ' . json_encode( $options ) . ';
101
  </script>
102
- <script type="text/javascript" src="' . $this->widget_url . '"></script>';
103
-
104
  echo apply_filters( 'cn_cookie_compliance_output', $output, $options );
105
  }
106
 
107
  /**
108
  * Cookie notice output.
109
- *
110
- * @return mixed
111
  */
112
  public function add_cookie_notice() {
 
 
 
113
  // WPML >= 3.2
114
  if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
115
- Cookie_Notice()->options['general']['message_text'] = apply_filters( 'wpml_translate_single_string', Cookie_Notice()->options['general']['message_text'], 'Cookie Notice', 'Message in the notice' );
116
- Cookie_Notice()->options['general']['accept_text'] = apply_filters( 'wpml_translate_single_string', Cookie_Notice()->options['general']['accept_text'], 'Cookie Notice', 'Button text' );
117
- Cookie_Notice()->options['general']['refuse_text'] = apply_filters( 'wpml_translate_single_string', Cookie_Notice()->options['general']['refuse_text'], 'Cookie Notice', 'Refuse button text' );
118
- Cookie_Notice()->options['general']['revoke_message_text'] = apply_filters( 'wpml_translate_single_string', Cookie_Notice()->options['general']['revoke_message_text'], 'Cookie Notice', 'Revoke message text' );
119
- Cookie_Notice()->options['general']['revoke_text'] = apply_filters( 'wpml_translate_single_string', Cookie_Notice()->options['general']['revoke_text'], 'Cookie Notice', 'Revoke button text' );
120
- Cookie_Notice()->options['general']['see_more_opt']['text'] = apply_filters( 'wpml_translate_single_string', Cookie_Notice()->options['general']['see_more_opt']['text'], 'Cookie Notice', 'Privacy policy text' );
121
- Cookie_Notice()->options['general']['see_more_opt']['link'] = apply_filters( 'wpml_translate_single_string', Cookie_Notice()->options['general']['see_more_opt']['link'], 'Cookie Notice', 'Custom link' );
122
  // WPML and Polylang compatibility
123
  } elseif ( function_exists( 'icl_t' ) ) {
124
- Cookie_Notice()->options['general']['message_text'] = icl_t( 'Cookie Notice', 'Message in the notice', Cookie_Notice()->options['general']['message_text'] );
125
- Cookie_Notice()->options['general']['accept_text'] = icl_t( 'Cookie Notice', 'Button text', Cookie_Notice()->options['general']['accept_text'] );
126
- Cookie_Notice()->options['general']['refuse_text'] = icl_t( 'Cookie Notice', 'Refuse button text', Cookie_Notice()->options['general']['refuse_text'] );
127
- Cookie_Notice()->options['general']['revoke_message_text'] = icl_t( 'Cookie Notice', 'Revoke message text', Cookie_Notice()->options['general']['revoke_message_text'] );
128
- Cookie_Notice()->options['general']['revoke_text'] = icl_t( 'Cookie Notice', 'Revoke button text', Cookie_Notice()->options['general']['revoke_text'] );
129
- Cookie_Notice()->options['general']['see_more_opt']['text'] = icl_t( 'Cookie Notice', 'Privacy policy text', Cookie_Notice()->options['general']['see_more_opt']['text'] );
130
- Cookie_Notice()->options['general']['see_more_opt']['link'] = icl_t( 'Cookie Notice', 'Custom link', Cookie_Notice()->options['general']['see_more_opt']['link'] );
131
  }
132
 
133
- if ( function_exists( 'icl_object_id' ) )
134
- Cookie_Notice()->options['general']['see_more_opt']['id'] = icl_object_id( Cookie_Notice()->options['general']['see_more_opt']['id'], 'page', true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
  // get cookie container args
137
  $options = apply_filters( 'cn_cookie_notice_args', array(
138
- 'position' => Cookie_Notice()->options['general']['position'],
139
- 'css_class' => Cookie_Notice()->options['general']['css_class'],
140
  'button_class' => 'cn-button',
141
- 'colors' => Cookie_Notice()->options['general']['colors'],
142
- 'message_text' => Cookie_Notice()->options['general']['message_text'],
143
- 'accept_text' => Cookie_Notice()->options['general']['accept_text'],
144
- 'refuse_text' => Cookie_Notice()->options['general']['refuse_text'],
145
- 'revoke_message_text' => Cookie_Notice()->options['general']['revoke_message_text'],
146
- 'revoke_text' => Cookie_Notice()->options['general']['revoke_text'],
147
- 'refuse_opt' => Cookie_Notice()->options['general']['refuse_opt'],
148
- 'revoke_cookies' => Cookie_Notice()->options['general']['revoke_cookies'],
149
- 'see_more' => Cookie_Notice()->options['general']['see_more'],
150
- 'see_more_opt' => Cookie_Notice()->options['general']['see_more_opt'],
151
- 'link_target' => Cookie_Notice()->options['general']['link_target'],
152
- 'link_position' => Cookie_Notice()->options['general']['link_position'],
153
  'aria_label' => 'Cookie Notice'
154
  ) );
155
 
156
  // check legacy parameters
157
- $options = Cookie_Notice()->check_legacy_params( $options, array( 'refuse_opt', 'see_more' ) );
158
 
159
  if ( $options['see_more'] === true )
160
  $options['message_text'] = do_shortcode( wp_kses_post( $options['message_text'] ) );
@@ -169,16 +211,16 @@ class Cookie_Notice_Frontend {
169
 
170
  // message output
171
  $output = '
172
- <!-- Cookie Notice plugin v' . Cookie_Notice()->defaults['version'] . ' by Hu-manity.co https://hu-manity.co/ -->
173
- <div id="cookie-notice" role="dialog" class="cookie-notice-hidden cookie-revoke-hidden cn-position-' . esc_attr( $options['position'] ) . '" aria-label="' . esc_attr( $options['aria_label'] ) . '" style="background-color: rgba(' . implode( ',', Cookie_Notice()->hex2rgb( $options['colors']['bar'] ) ) . ',' . ( (int) $options['colors']['bar_opacity'] ) * 0.01 . ');">'
174
  . '<div class="cookie-notice-container" style="color: ' . esc_attr( $options['colors']['text'] ) . ';">'
175
  . '<span id="cn-notice-text" class="cn-text-container">'. $options['message_text'] . '</span>'
176
  . '<span id="cn-notice-buttons" class="cn-buttons-container"><a href="#" id="cn-accept-cookie" data-cookie-set="accept" class="cn-set-cookie ' . $options['button_class'] . ( $options['css_class'] !== '' ? ' cn-button-custom ' . $options['css_class'] : '' ) . '" aria-label="' . esc_attr( $options['accept_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['accept_text'] ) . '</a>'
177
  . ( $options['refuse_opt'] === true ? '<a href="#" id="cn-refuse-cookie" data-cookie-set="refuse" class="cn-set-cookie ' . $options['button_class'] . ( $options['css_class'] !== '' ? ' cn-button-custom ' . $options['css_class'] : '' ) . '" aria-label="' . esc_attr( $options['refuse_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['refuse_text'] ) . '</a>' : '' )
178
- . ( $options['see_more'] === true && $options['link_position'] === 'banner' ? '<a href="' . ( $options['see_more_opt']['link_type'] === 'custom' ? esc_url( $options['see_more_opt']['link'] ) : get_permalink( $options['see_more_opt']['id'] ) ) . '" target="' . esc_attr( $options['link_target'] ) . '" id="cn-more-info" class="cn-more-info ' . $options['button_class'] . ( $options['css_class'] !== '' ? ' cn-button-custom ' . $options['css_class'] : '' ) . '" aria-label="' . esc_attr( $options['see_more_opt']['text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['see_more_opt']['text'] ) . '</a>' : '' )
179
  . '</span><span id="cn-close-notice" data-cookie-set="accept" class="cn-close-icon" title="' . esc_attr( $options['refuse_text'] ) . '"></span>'
180
  . '</div>
181
- ' . ( $options['refuse_opt'] === true && $options['revoke_cookies'] == true ?
182
  '<div class="cookie-revoke-container" style="color: ' . esc_attr( $options['colors']['text'] ) . ';">'
183
  . ( ! empty( $options['revoke_message_text'] ) ? '<span id="cn-revoke-text" class="cn-text-container">' . $options['revoke_message_text'] . '</span>' : '' )
184
  . '<span id="cn-revoke-buttons" class="cn-buttons-container"><a href="#" class="cn-revoke-cookie ' . $options['button_class'] . ( $options['css_class'] !== '' ? ' cn-button-custom ' . $options['css_class'] : '' ) . '" aria-label="' . esc_attr( $options['revoke_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['revoke_text'] ) . '</a></span>
@@ -188,60 +230,64 @@ class Cookie_Notice_Frontend {
188
 
189
  echo apply_filters( 'cn_cookie_notice_output', $output, $options );
190
  }
191
-
192
  /**
193
  * Load notice scripts and styles - frontend.
 
 
194
  */
195
  public function wp_enqueue_notice_scripts() {
196
- wp_enqueue_script( 'cookie-notice-front', plugins_url( '../js/front' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', __FILE__ ), array(), Cookie_Notice()->defaults['version'], isset( Cookie_Notice()->options['general']['script_placement'] ) && Cookie_Notice()->options['general']['script_placement'] === 'footer' );
 
 
 
197
 
198
  wp_localize_script(
199
  'cookie-notice-front',
200
  'cnArgs',
201
- array(
202
  'ajaxUrl' => admin_url( 'admin-ajax.php' ),
203
  'nonce' => wp_create_nonce( 'cn_save_cases' ),
204
- 'hideEffect' => Cookie_Notice()->options['general']['hide_effect'],
205
- 'position' => Cookie_Notice()->options['general']['position'],
206
- 'onScroll' => (int) Cookie_Notice()->options['general']['on_scroll'],
207
- 'onScrollOffset' => (int) Cookie_Notice()->options['general']['on_scroll_offset'],
208
- 'onClick' => (int) Cookie_Notice()->options['general']['on_click'],
209
  'cookieName' => 'cookie_notice_accepted',
210
- 'cookieTime' => Cookie_Notice()->settings->times[Cookie_Notice()->options['general']['time']][1],
211
- 'cookieTimeRejected' => Cookie_Notice()->settings->times[Cookie_Notice()->options['general']['time_rejected']][1],
212
- 'cookiePath' => ( defined( 'COOKIEPATH' ) ? (string) COOKIEPATH : '' ),
213
- 'cookieDomain' => ( defined( 'COOKIE_DOMAIN' ) ? (string) COOKIE_DOMAIN : '' ),
214
- 'redirection' => (int) Cookie_Notice()->options['general']['redirection'],
215
  'cache' => (int) ( defined( 'WP_CACHE' ) && WP_CACHE ),
216
- 'refuse' => (int) Cookie_Notice()->options['general']['refuse_opt'],
217
- 'revokeCookies' => (int) Cookie_Notice()->options['general']['revoke_cookies'],
218
- 'revokeCookiesOpt' => Cookie_Notice()->options['general']['revoke_cookies_opt'],
219
  'secure' => (int) is_ssl()
220
- )
221
  );
222
 
223
  wp_enqueue_style( 'cookie-notice-front', plugins_url( '../css/front' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', __FILE__ ) );
224
  }
225
-
226
  /**
227
- * Make a JavaScript Asynchronous
228
- *
229
  * @param string $tag The original enqueued script tag
230
  * @param string $handle The registered unique name of the script
231
  * @param string $src
232
  * @return string $tag The modified script tag
233
  */
234
  public function wp_enqueue_script_async( $tag, $handle, $src ) {
235
- if ( 'cookie-notice-front' === $handle ) {
236
  $tag = str_replace( '<script', '<script async', $tag );
237
- }
238
  return $tag;
239
  }
240
 
241
  /**
242
  * Print non functional JavaScript in body.
243
  *
244
- * @return mixed
245
  */
246
  public function wp_print_footer_scripts() {
247
  if ( Cookie_Notice()->cookies_accepted() ) {
@@ -255,7 +301,7 @@ class Cookie_Notice_Frontend {
255
  /**
256
  * Print non functional JavaScript in header.
257
  *
258
- * @return mixed
259
  */
260
  public function wp_print_header_scripts() {
261
  if ( Cookie_Notice()->cookies_accepted() ) {
@@ -263,9 +309,9 @@ class Cookie_Notice_Frontend {
263
 
264
  if ( ! empty( $scripts ) )
265
  echo $scripts;
266
- }
267
  }
268
-
269
  /**
270
  * Add new body classes.
271
  *
@@ -291,6 +337,8 @@ class Cookie_Notice_Frontend {
291
 
292
  /**
293
  * Purge config cache.
 
 
294
  */
295
  public function purge_cache() {
296
  delete_transient( 'cookie_notice_compliance_cache' );
5
 
6
  /**
7
  * Cookie_Notice_Frontend class.
8
+ *
9
  * @class Cookie_Notice_Frontend
10
  */
11
  class Cookie_Notice_Frontend {
12
+
13
  private $is_bot = false;
14
  private $hide_banner = false;
 
 
 
 
15
 
16
+ /**
17
+ * Class constructor.
18
+ *
19
+ * @return void
20
+ */
21
  public function __construct() {
22
  // actions
23
  add_action( 'init', array( $this, 'init' ) );
24
  }
25
 
26
  /**
27
+ * Initialize frontend.
28
+ *
29
+ * @global string $pagenow
30
+ *
31
+ * @return void
32
  */
33
  public function init() {
34
  // purge cache
40
 
41
  // is it a bot?
42
  $this->is_bot = Cookie_Notice()->bot_detect->is_crawler();
43
+
44
  // is user logged in and hiding the banner is enabled
45
  $this->hide_banner = is_user_logged_in() && Cookie_Notice()->options['general']['hide_banner'] === true;
46
 
69
 
70
  /**
71
  * Add CORS header for API requests and purge cache.
72
+ *
73
+ * @return void
74
  */
75
  public function add_compliance_http_header() {
76
+ header( 'Access-Control-Allow-Origin: ' . Cookie_Notice()->get_url( 'host' ) );
77
  header( 'Access-Control-Allow-Methods: GET' );
78
  }
79
 
83
  * @return void
84
  */
85
  public function add_cookie_compliance() {
86
+ // get main instance
87
+ $cn = Cookie_Notice();
88
+
89
  // get site language
90
  $locale = get_locale();
91
  $locale_code = explode( '_', $locale );
92
 
93
  // exceptions, norwegian
94
+ if ( in_array( $locale_code, [ 'nb', 'nn' ] ) )
95
  $locale_code = 'no';
96
 
97
+ $options = apply_filters(
98
+ 'cn_cookie_compliance_args',
99
+ [
100
+ 'appID' => $cn->options['general']['app_id'],
101
+ 'currentLanguage' => $locale_code[0],
102
+ 'blocking' => ( ! is_user_logged_in() ? (bool) $cn->options['general']['app_blocking'] : false ),
103
+ 'globalCookie' => ( is_multisite() && $cn->options['general']['global_cookie'] && is_subdomain_install() )
104
+ ]
105
+ );
106
+
107
+ if ( $cn->options['general']['debug_mode'] )
108
  $options['debugMode'] = true;
109
+
 
110
  // message output
111
  $output = '
112
  <!-- Hu Banner -->
113
  <script type="text/javascript">
114
  var huOptions = ' . json_encode( $options ) . ';
115
  </script>
116
+ <script type="text/javascript" src="' . $cn->get_url( 'widget' ) . '"></script>';
117
+
118
  echo apply_filters( 'cn_cookie_compliance_output', $output, $options );
119
  }
120
 
121
  /**
122
  * Cookie notice output.
123
+ *
124
+ * @return void
125
  */
126
  public function add_cookie_notice() {
127
+ // get main instance
128
+ $cn = Cookie_Notice();
129
+
130
  // WPML >= 3.2
131
  if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
132
+ $cn->options['general']['message_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['message_text'], 'Cookie Notice', 'Message in the notice' );
133
+ $cn->options['general']['accept_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['accept_text'], 'Cookie Notice', 'Button text' );
134
+ $cn->options['general']['refuse_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['refuse_text'], 'Cookie Notice', 'Refuse button text' );
135
+ $cn->options['general']['revoke_message_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['revoke_message_text'], 'Cookie Notice', 'Revoke message text' );
136
+ $cn->options['general']['revoke_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['revoke_text'], 'Cookie Notice', 'Revoke button text' );
137
+ $cn->options['general']['see_more_opt']['text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['see_more_opt']['text'], 'Cookie Notice', 'Privacy policy text' );
138
+ $cn->options['general']['see_more_opt']['link'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['see_more_opt']['link'], 'Cookie Notice', 'Custom link' );
139
  // WPML and Polylang compatibility
140
  } elseif ( function_exists( 'icl_t' ) ) {
141
+ $cn->options['general']['message_text'] = icl_t( 'Cookie Notice', 'Message in the notice', $cn->options['general']['message_text'] );
142
+ $cn->options['general']['accept_text'] = icl_t( 'Cookie Notice', 'Button text', $cn->options['general']['accept_text'] );
143
+ $cn->options['general']['refuse_text'] = icl_t( 'Cookie Notice', 'Refuse button text', $cn->options['general']['refuse_text'] );
144
+ $cn->options['general']['revoke_message_text'] = icl_t( 'Cookie Notice', 'Revoke message text', $cn->options['general']['revoke_message_text'] );
145
+ $cn->options['general']['revoke_text'] = icl_t( 'Cookie Notice', 'Revoke button text', $cn->options['general']['revoke_text'] );
146
+ $cn->options['general']['see_more_opt']['text'] = icl_t( 'Cookie Notice', 'Privacy policy text', $cn->options['general']['see_more_opt']['text'] );
147
+ $cn->options['general']['see_more_opt']['link'] = icl_t( 'Cookie Notice', 'Custom link', $cn->options['general']['see_more_opt']['link'] );
148
  }
149
 
150
+ if ( $cn->options['general']['see_more_opt']['link_type'] === 'page' ) {
151
+ // multisite with global override?
152
+ if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
153
+ // get main site id
154
+ $main_site_id = get_main_site_id();
155
+
156
+ // switch to main site
157
+ switch_to_blog( $main_site_id );
158
+
159
+ // update page id for current language if needed
160
+ if ( function_exists( 'icl_object_id' ) )
161
+ $cn->options['general']['see_more_opt']['id'] = icl_object_id( $cn->options['general']['see_more_opt']['id'], 'page', true );
162
+
163
+ // get main site privacy policy link
164
+ $permalink = get_permalink( $cn->options['general']['see_more_opt']['id'] );
165
+
166
+ // restore current site
167
+ restore_current_blog();
168
+ } else {
169
+ // update page id for current language if needed
170
+ if ( function_exists( 'icl_object_id' ) )
171
+ $cn->options['general']['see_more_opt']['id'] = icl_object_id( $cn->options['general']['see_more_opt']['id'], 'page', true );
172
+
173
+ // get privacy policy link
174
+ $permalink = get_permalink( $cn->options['general']['see_more_opt']['id'] );
175
+ }
176
+ }
177
 
178
  // get cookie container args
179
  $options = apply_filters( 'cn_cookie_notice_args', array(
180
+ 'position' => $cn->options['general']['position'],
181
+ 'css_class' => $cn->options['general']['css_class'],
182
  'button_class' => 'cn-button',
183
+ 'colors' => $cn->options['general']['colors'],
184
+ 'message_text' => $cn->options['general']['message_text'],
185
+ 'accept_text' => $cn->options['general']['accept_text'],
186
+ 'refuse_text' => $cn->options['general']['refuse_text'],
187
+ 'revoke_message_text' => $cn->options['general']['revoke_message_text'],
188
+ 'revoke_text' => $cn->options['general']['revoke_text'],
189
+ 'refuse_opt' => $cn->options['general']['refuse_opt'],
190
+ 'revoke_cookies' => $cn->options['general']['revoke_cookies'],
191
+ 'see_more' => $cn->options['general']['see_more'],
192
+ 'see_more_opt' => $cn->options['general']['see_more_opt'],
193
+ 'link_target' => $cn->options['general']['link_target'],
194
+ 'link_position' => $cn->options['general']['link_position'],
195
  'aria_label' => 'Cookie Notice'
196
  ) );
197
 
198
  // check legacy parameters
199
+ $options = $cn->check_legacy_params( $options, array( 'refuse_opt', 'see_more' ) );
200
 
201
  if ( $options['see_more'] === true )
202
  $options['message_text'] = do_shortcode( wp_kses_post( $options['message_text'] ) );
211
 
212
  // message output
213
  $output = '
214
+ <!-- Cookie Notice plugin v' . $cn->defaults['version'] . ' by Hu-manity.co https://hu-manity.co/ -->
215
+ <div id="cookie-notice" role="dialog" class="cookie-notice-hidden cookie-revoke-hidden cn-position-' . esc_attr( $options['position'] ) . '" aria-label="' . esc_attr( $options['aria_label'] ) . '" style="background-color: rgba(' . implode( ',', $cn->hex2rgb( $options['colors']['bar'] ) ) . ',' . ( (int) $options['colors']['bar_opacity'] ) * 0.01 . ');">'
216
  . '<div class="cookie-notice-container" style="color: ' . esc_attr( $options['colors']['text'] ) . ';">'
217
  . '<span id="cn-notice-text" class="cn-text-container">'. $options['message_text'] . '</span>'
218
  . '<span id="cn-notice-buttons" class="cn-buttons-container"><a href="#" id="cn-accept-cookie" data-cookie-set="accept" class="cn-set-cookie ' . $options['button_class'] . ( $options['css_class'] !== '' ? ' cn-button-custom ' . $options['css_class'] : '' ) . '" aria-label="' . esc_attr( $options['accept_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['accept_text'] ) . '</a>'
219
  . ( $options['refuse_opt'] === true ? '<a href="#" id="cn-refuse-cookie" data-cookie-set="refuse" class="cn-set-cookie ' . $options['button_class'] . ( $options['css_class'] !== '' ? ' cn-button-custom ' . $options['css_class'] : '' ) . '" aria-label="' . esc_attr( $options['refuse_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['refuse_text'] ) . '</a>' : '' )
220
+ . ( $options['see_more'] === true && $options['link_position'] === 'banner' ? '<a href="' . ( $options['see_more_opt']['link_type'] === 'custom' ? esc_url( $options['see_more_opt']['link'] ) : esc_url( $permalink ) ) . '" target="' . esc_attr( $options['link_target'] ) . '" id="cn-more-info" class="cn-more-info ' . $options['button_class'] . ( $options['css_class'] !== '' ? ' cn-button-custom ' . $options['css_class'] : '' ) . '" aria-label="' . esc_attr( $options['see_more_opt']['text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['see_more_opt']['text'] ) . '</a>' : '' )
221
  . '</span><span id="cn-close-notice" data-cookie-set="accept" class="cn-close-icon" title="' . esc_attr( $options['refuse_text'] ) . '"></span>'
222
  . '</div>
223
+ ' . ( $options['refuse_opt'] === true && $options['revoke_cookies'] == true ?
224
  '<div class="cookie-revoke-container" style="color: ' . esc_attr( $options['colors']['text'] ) . ';">'
225
  . ( ! empty( $options['revoke_message_text'] ) ? '<span id="cn-revoke-text" class="cn-text-container">' . $options['revoke_message_text'] . '</span>' : '' )
226
  . '<span id="cn-revoke-buttons" class="cn-buttons-container"><a href="#" class="cn-revoke-cookie ' . $options['button_class'] . ( $options['css_class'] !== '' ? ' cn-button-custom ' . $options['css_class'] : '' ) . '" aria-label="' . esc_attr( $options['revoke_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['revoke_text'] ) . '</a></span>
230
 
231
  echo apply_filters( 'cn_cookie_notice_output', $output, $options );
232
  }
233
+
234
  /**
235
  * Load notice scripts and styles - frontend.
236
+ *
237
+ * @return void
238
  */
239
  public function wp_enqueue_notice_scripts() {
240
+ // get main instance
241
+ $cn = Cookie_Notice();
242
+
243
+ wp_enqueue_script( 'cookie-notice-front', plugins_url( '../js/front' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', __FILE__ ), array(), $cn->defaults['version'], isset( $cn->options['general']['script_placement'] ) && $cn->options['general']['script_placement'] === 'footer' );
244
 
245
  wp_localize_script(
246
  'cookie-notice-front',
247
  'cnArgs',
248
+ [
249
  'ajaxUrl' => admin_url( 'admin-ajax.php' ),
250
  'nonce' => wp_create_nonce( 'cn_save_cases' ),
251
+ 'hideEffect' => $cn->options['general']['hide_effect'],
252
+ 'position' => $cn->options['general']['position'],
253
+ 'onScroll' => (int) $cn->options['general']['on_scroll'],
254
+ 'onScrollOffset' => (int) $cn->options['general']['on_scroll_offset'],
255
+ 'onClick' => (int) $cn->options['general']['on_click'],
256
  'cookieName' => 'cookie_notice_accepted',
257
+ 'cookieTime' => $cn->settings->times[$cn->options['general']['time']][1],
258
+ 'cookieTimeRejected' => $cn->settings->times[$cn->options['general']['time_rejected']][1],
259
+ 'globalCookie' => (int) ( is_multisite() && $cn->options['general']['global_cookie'] && is_subdomain_install() ),
260
+ 'redirection' => (int) $cn->options['general']['redirection'],
 
261
  'cache' => (int) ( defined( 'WP_CACHE' ) && WP_CACHE ),
262
+ 'refuse' => (int) $cn->options['general']['refuse_opt'],
263
+ 'revokeCookies' => (int) $cn->options['general']['revoke_cookies'],
264
+ 'revokeCookiesOpt' => $cn->options['general']['revoke_cookies_opt'],
265
  'secure' => (int) is_ssl()
266
+ ]
267
  );
268
 
269
  wp_enqueue_style( 'cookie-notice-front', plugins_url( '../css/front' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', __FILE__ ) );
270
  }
271
+
272
  /**
273
+ * Make a JavaScript Asynchronous.
274
+ *
275
  * @param string $tag The original enqueued script tag
276
  * @param string $handle The registered unique name of the script
277
  * @param string $src
278
  * @return string $tag The modified script tag
279
  */
280
  public function wp_enqueue_script_async( $tag, $handle, $src ) {
281
+ if ( 'cookie-notice-front' === $handle )
282
  $tag = str_replace( '<script', '<script async', $tag );
283
+
284
  return $tag;
285
  }
286
 
287
  /**
288
  * Print non functional JavaScript in body.
289
  *
290
+ * @return void
291
  */
292
  public function wp_print_footer_scripts() {
293
  if ( Cookie_Notice()->cookies_accepted() ) {
301
  /**
302
  * Print non functional JavaScript in header.
303
  *
304
+ * @return void
305
  */
306
  public function wp_print_header_scripts() {
307
  if ( Cookie_Notice()->cookies_accepted() ) {
309
 
310
  if ( ! empty( $scripts ) )
311
  echo $scripts;
312
+ }
313
  }
314
+
315
  /**
316
  * Add new body classes.
317
  *
337
 
338
  /**
339
  * Purge config cache.
340
+ *
341
+ * @return void
342
  */
343
  public function purge_cache() {
344
  delete_transient( 'cookie_notice_compliance_cache' );
includes/settings.php CHANGED
@@ -1,1082 +1,1340 @@
1
- <?php
2
- // exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) )
4
- exit;
5
-
6
- /**
7
- * Cookie_Notice_Settings class.
8
- *
9
- * @class Cookie_Notice_Settings
10
- */
11
- class Cookie_Notice_Settings {
12
- private $app_login_url = 'https://app.hu-manity.co/#/en/cc2/login';
13
-
14
- public $positions = array();
15
- public $styles = array();
16
- public $choices = array();
17
- public $links = array();
18
- public $link_targets = array();
19
- public $link_positions = array();
20
- public $colors = array();
21
- public $options = array();
22
- public $effects = array();
23
- public $times = array();
24
- public $notices = array();
25
- public $script_placements = array();
26
- public $countries = array();
27
- public $level_names = array();
28
- public $text_strings = array();
29
-
30
- public function __construct() {
31
- // actions
32
- add_action( 'admin_menu', array( $this, 'admin_menu_options' ) );
33
- add_action( 'after_setup_theme', array( $this, 'load_defaults' ) );
34
- add_action( 'admin_init', array( $this, 'register_settings' ) );
35
- add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
36
- add_action( 'admin_print_styles', array( $this, 'admin_print_styles' ) );
37
- add_action( 'wp_ajax_cn_purge_cache', array( $this, 'ajax_purge_cache' ) );
38
- add_action( 'admin_notices', array( $this, 'settings_errors' ) );
39
- }
40
-
41
- /**
42
- * Load plugin defaults
43
- */
44
- public function load_defaults() {
45
- $this->positions = array(
46
- 'top' => __( 'Top', 'cookie-notice' ),
47
- 'bottom' => __( 'Bottom', 'cookie-notice' )
48
- );
49
-
50
- $this->styles = array(
51
- 'none' => __( 'None', 'cookie-notice' ),
52
- 'wp-default' => __( 'Light', 'cookie-notice' ),
53
- 'bootstrap' => __( 'Dark', 'cookie-notice' )
54
- );
55
-
56
- $this->revoke_opts = array(
57
- 'automatic' => __( 'Automatic', 'cookie-notice' ),
58
- 'manual' => __( 'Manual', 'cookie-notice' )
59
- );
60
-
61
- $this->links = array(
62
- 'page' => __( 'Page link', 'cookie-notice' ),
63
- 'custom' => __( 'Custom link', 'cookie-notice' )
64
- );
65
-
66
- $this->link_targets = array(
67
- '_blank',
68
- '_self'
69
- );
70
-
71
- $this->link_positions = array(
72
- 'banner' => __( 'Banner', 'cookie-notice' ),
73
- 'message' => __( 'Message', 'cookie-notice' )
74
- );
75
-
76
- $this->colors = array(
77
- 'text' => __( 'Text color', 'cookie-notice' ),
78
- 'button' => __( 'Button color', 'cookie-notice' ),
79
- 'bar' => __( 'Bar color', 'cookie-notice' ),
80
- );
81
-
82
- $this->times = apply_filters(
83
- 'cn_cookie_expiry',
84
- array(
85
- 'hour' => array( __( 'An hour', 'cookie-notice' ), 3600 ),
86
- 'day' => array( __( '1 day', 'cookie-notice' ), 86400 ),
87
- 'week' => array( __( '1 week', 'cookie-notice' ), 604800 ),
88
- 'month' => array( __( '1 month', 'cookie-notice' ), 2592000 ),
89
- '3months' => array( __( '3 months', 'cookie-notice' ), 7862400 ),
90
- '6months' => array( __( '6 months', 'cookie-notice' ), 15811200 ),
91
- 'year' => array( __( '1 year', 'cookie-notice' ), 31536000 ),
92
- 'infinity' => array( __( 'infinity', 'cookie-notice' ), 2147483647 )
93
- )
94
- );
95
-
96
- $this->effects = array(
97
- 'none' => __( 'None', 'cookie-notice' ),
98
- 'fade' => __( 'Fade', 'cookie-notice' ),
99
- 'slide' => __( 'Slide', 'cookie-notice' )
100
- );
101
-
102
- $this->script_placements = array(
103
- 'header' => __( 'Header', 'cookie-notice' ),
104
- 'footer' => __( 'Footer', 'cookie-notice' ),
105
- );
106
-
107
- $this->level_names = array(
108
- 1 => array(
109
- 1 => __( 'Silver', 'cookie-notice' ),
110
- 2 => __( 'Gold', 'cookie-notice' ),
111
- 3 => __( 'Platinum', 'cookie-notice' )
112
- ),
113
- 2 => array(
114
- 1 => __( 'Private', 'cookie-notice' ),
115
- 2 => __( 'Balanced', 'cookie-notice' ),
116
- 3 => __( 'Personalized', 'cookie-notice' )
117
- ),
118
- 3 => array(
119
- 1 => __( 'Reject All', 'cookie-notice' ),
120
- 2 => __( 'Accept Some', 'cookie-notice' ),
121
- 3 => __( 'Accept All', 'cookie-notice' )
122
- )
123
- );
124
-
125
- $this->text_strings = array(
126
- 'saveBtnText' => __( 'Save my preferences', 'cookie-notice' ),
127
- // 'acceptBtnText' => __( 'Accept', 'cookie-notice' ),
128
- // 'rejectBtnText' => __( 'Reject', 'cookie-notice' ),
129
- // 'revokeBtnText' => __( 'Revoke Cookies', 'cookie-notice' ),
130
- 'privacyBtnText' => __( 'Privacy policy', 'cookie-notice' ),
131
- 'dontSellBtnText' => __( 'Do Not Sell', 'cookie-notice' ),
132
- 'customizeBtnText' => __( 'Preferences', 'cookie-notice' ),
133
- 'headingText' => __( "We believe your data is your property and support your right to privacy and transparency.", 'cookie-notice' ),
134
- 'bodyText' => __( "Select a Data Access Level and Duration to choose how we use and share your data.", 'cookie-notice' ),
135
- 'levelBodyText_1' => __( 'Highest level of privacy. Data accessed for necessary site operations only. Data shared with 3rd parties to ensure the site is secure and works on your device.', 'cookie-notice' ),
136
- 'levelBodyText_2' => __( 'Balanced experience. Data accessed for content personalisation and site optimisation. Data shared with 3rd parties may be used to track and store your preferences for this site.', 'cookie-notice' ),
137
- 'levelBodyText_3' => __( 'Highest level of personalisation. Data accessed to make ads and media more relevant. Data shared with 3rd parties may be use to track you on this site and other sites you visit.', 'cookie-notice' ),
138
- 'levelNameText_1' => $this->level_names[1][1],
139
- 'levelNameText_2' => $this->level_names[1][2],
140
- 'levelNameText_3' => $this->level_names[1][3],
141
- 'monthText' => __( 'month', 'cookie-notice' ),
142
- 'monthsText' => __( 'months', 'cookie-notice' )
143
- );
144
-
145
- // set default text strings
146
- Cookie_Notice()->defaults['general']['message_text'] = __( 'We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.', 'cookie-notice' );
147
- Cookie_Notice()->defaults['general']['accept_text'] = __( 'Ok', 'cookie-notice' );
148
- Cookie_Notice()->defaults['general']['refuse_text'] = __( 'No', 'cookie-notice' );
149
- Cookie_Notice()->defaults['general']['revoke_message_text'] = __( 'You can revoke your consent any time using the Revoke consent button.', 'cookie-notice' );
150
- Cookie_Notice()->defaults['general']['revoke_text'] = __( 'Revoke consent', 'cookie-notice' );
151
- Cookie_Notice()->defaults['general']['see_more_opt']['text'] = __( 'Privacy policy', 'cookie-notice' );
152
-
153
- // set translation strings on plugin activation
154
- if ( Cookie_Notice()->options['general']['translate'] === true ) {
155
- Cookie_Notice()->options['general']['translate'] = false;
156
-
157
- Cookie_Notice()->options['general']['message_text'] = Cookie_Notice()->defaults['general']['message_text'];
158
- Cookie_Notice()->options['general']['accept_text'] = Cookie_Notice()->defaults['general']['accept_text'];
159
- Cookie_Notice()->options['general']['refuse_text'] = Cookie_Notice()->defaults['general']['refuse_text'];
160
- Cookie_Notice()->options['general']['revoke_message_text'] = Cookie_Notice()->defaults['general']['revoke_message_text'];
161
- Cookie_Notice()->options['general']['revoke_text'] = Cookie_Notice()->defaults['general']['revoke_text'];
162
- Cookie_Notice()->options['general']['see_more_opt']['text'] = Cookie_Notice()->defaults['general']['see_more_opt']['text'];
163
-
164
- update_option( 'cookie_notice_options', Cookie_Notice()->options['general'] );
165
- }
166
-
167
- // WPML >= 3.2
168
- if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
169
- $this->register_wpml_strings();
170
- // WPML and Polylang compatibility
171
- } elseif ( function_exists( 'icl_register_string' ) ) {
172
- icl_register_string( 'Cookie Notice', 'Message in the notice', Cookie_Notice()->options['general']['message_text'] );
173
- icl_register_string( 'Cookie Notice', 'Button text', Cookie_Notice()->options['general']['accept_text'] );
174
- icl_register_string( 'Cookie Notice', 'Refuse button text', Cookie_Notice()->options['general']['refuse_text'] );
175
- icl_register_string( 'Cookie Notice', 'Revoke message text', Cookie_Notice()->options['general']['revoke_message_text'] );
176
- icl_register_string( 'Cookie Notice', 'Revoke button text', Cookie_Notice()->options['general']['revoke_text'] );
177
- icl_register_string( 'Cookie Notice', 'Privacy policy text', Cookie_Notice()->options['general']['see_more_opt']['text'] );
178
- icl_register_string( 'Cookie Notice', 'Custom link', Cookie_Notice()->options['general']['see_more_opt']['link'] );
179
- }
180
- }
181
-
182
- /**
183
- * Add submenu.
184
- */
185
- public function admin_menu_options() {
186
- add_menu_page( __( 'Cookie Notice', 'cookie-notice' ), __( 'Cookies', 'cookie-notice' ), apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ), 'cookie-notice', array( $this, 'options_page' ), 'none', '99.3' );
187
- }
188
-
189
- /**
190
- * Options page output.
191
- *
192
- * @return mixed
193
- */
194
- public function options_page() {
195
- echo '
196
- <div class="wrap">
197
- <h2>' . __( 'Cookie Notice & Compliance for GDPR/CCPA', 'cookie-notice' ) . '</h2>
198
- <div class="cookie-notice-settings">
199
- <div class="cookie-notice-sidebar">
200
- <div class="cookie-notice-credits">
201
- <div class="inside">
202
- <div class="inner">';
203
-
204
- // compliance enabled
205
- if ( Cookie_Notice()->get_status() === 'active' ) {
206
- echo ' <h2>We\'re Promoting Privacy&trade;</h2>
207
- <p>' . __( 'Promote the privacy of your website visitors without affecting how you do your business.', 'cookie-notice' ) . '</p>';
208
- } else {
209
- echo ' <h1><b>Cookie Compliance&trade;</b></h1>
210
- <h2>' . __( 'The next generation of Cookie Notice', 'cookie-notice' ) . '</h2>
211
- <div class="cn-lead">
212
- <p>' . __( 'A free web application to help you deliver better consent experiences and comply with GDPR, CCPA and other data privacy laws more effectively.', 'cookie-notice' ) . '</p>
213
- </div>
214
- <img src="//cns2-53eb.kxcdn.com/screen-dashboard-small.png">
215
- <a href="https://cookie-compliance.co/" class="button button-primary button-hero cn-button" target="_blank">' . __( 'Learn more', 'cookie-notice' ) . '</a>';
216
- }
217
-
218
- echo '
219
- </div>
220
- </div>
221
- </div>';
222
-
223
- if ( Cookie_Notice()->get_status() !== 'active' ) {
224
- echo '
225
- <div class="cookie-notice-faq">
226
- <h2>' . __( 'F.A.Q.', 'cookie-notice' ) . '</h2>
227
- <div class="cn-toggle-container">
228
- <label for="cn-faq-1" class="cn-toggle-item">
229
- <input id="cn-faq-1" type="checkbox" checked />
230
- <span class="cn-toggle-heading">' . __( 'Does the Cookie Notice make my site fully compliant with GDPR?', 'cookie-notice' ) . '</span>
231
- <span class="cn-toggle-body">' . __( 'It is not possible to provide the required technical compliance features using only a WordPress plugin. Features like consent record storage, purpose categories and script blocking that bring your site into full compliance with GDPR are only available through the Cookie Compliance integration.', 'cookie-notice' ) . '
232
- </label>
233
- <label for="cn-faq-2" class="cn-toggle-item">
234
- <input id="cn-faq-2" type="checkbox" />
235
- <span class="cn-toggle-heading">' . __( 'Does the Cookie Compiance integration make my site fully compliant with GDPR?', 'cookie-notice' ) . '</span>
236
- <span class="cn-toggle-body">' . __( 'Yes! The plugin + web application version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions.', 'cookie-notice' ) . '</span>
237
- </label>
238
- <label for="cn-faq-3" class="cn-toggle-item">
239
- <input id="cn-faq-3" type="checkbox" />
240
- <span class="cn-toggle-heading">' . __( 'Is Cookie Compliance free?', 'cookie-notice' ) . '</span>
241
- <span class="cn-toggle-body">' . __( 'Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website monthly traffic.', 'cookie-notice' ) . '</span>
242
- </label>
243
- <label for="cn-faq-4" class="cn-toggle-item">
244
- <input id="cn-faq-4" type="checkbox" />
245
- <span class="cn-toggle-heading">' . __( 'Where can I find pricing options?', 'cookie-notice' ) . '</span>
246
- <span class="cn-toggle-body">' . __( 'You can learn more about the features and pricing by visiting the Cookie Compliance website here:', 'cookie-notice' ) . ' <a href="https://cookie-compliance.co/" target="_blank">https://cookie-compliance.co/</a></span>
247
- </label>
248
- </div>
249
- </div>';
250
- }
251
-
252
- echo '
253
- </div>
254
- <form action="options.php" method="post">';
255
-
256
- settings_fields( 'cookie_notice_options' );
257
- do_settings_sections( 'cookie_notice_options' );
258
-
259
- echo '
260
- <p class="submit">';
261
- submit_button( '', 'primary', 'save_cookie_notice_options', false );
262
- echo ' ';
263
- submit_button( __( 'Reset to defaults', 'cookie-notice' ), 'secondary', 'reset_cookie_notice_options', false );
264
- echo '
265
- </p>
266
- </form>
267
- </div>
268
- <div class="clear"></div>
269
- </div>';
270
- }
271
-
272
- /**
273
- * Regiseter plugin settings.
274
- */
275
- public function register_settings() {
276
- register_setting( 'cookie_notice_options', 'cookie_notice_options', array( $this, 'validate_options' ) );
277
-
278
- // compliance enabled
279
- if ( Cookie_Notice()->get_status() === 'active' ) {
280
- // configuration
281
- add_settings_section( 'cookie_notice_compliance', __( 'Compliance Settings', 'cookie-notice' ), array( $this, 'cn_section_compliance' ), 'cookie_notice_options' );
282
- add_settings_field( 'cn_app_status', __( 'Compliance status', 'cookie-notice' ), array( $this, 'cn_app_status' ), 'cookie_notice_options', 'cookie_notice_compliance' );
283
- add_settings_field( 'cn_app_id', __( 'App ID', 'cookie-notice' ), array( $this, 'cn_app_id' ), 'cookie_notice_options', 'cookie_notice_compliance' );
284
- add_settings_field( 'cn_app_key', __( 'App Key', 'cookie-notice' ), array( $this, 'cn_app_key' ), 'cookie_notice_options', 'cookie_notice_compliance' );
285
-
286
- add_settings_section( 'cookie_notice_configuration', __( 'Miscellaneous Settings', 'cookie-notice' ), array( $this, 'cn_section_configuration' ), 'cookie_notice_options' );
287
- add_settings_field( 'cn_app_blocking', __( 'Autoblocking', 'cookie-notice' ), array( $this, 'cn_app_blocking' ), 'cookie_notice_options', 'cookie_notice_configuration' );
288
- add_settings_field( 'cn_hide_banner', __( 'Hide for logged in', 'cookie-notice' ), array( $this, 'cn_hide_banner' ), 'cookie_notice_options', 'cookie_notice_configuration' );
289
- add_settings_field( 'cn_debug_mode', __( 'Debug mode', 'cookie-notice' ), array( $this, 'cn_debug_mode' ), 'cookie_notice_options', 'cookie_notice_configuration' );
290
- add_settings_field( 'cn_app_purge_cache', __( 'Cache', 'cookie-notice' ), array( $this, 'cn_app_purge_cache' ), 'cookie_notice_options', 'cookie_notice_configuration' );
291
- add_settings_field( 'cn_script_placement', __( 'Script placement', 'cookie-notice' ), array( $this, 'cn_script_placement' ), 'cookie_notice_options', 'cookie_notice_configuration' );
292
- add_settings_field( 'cn_deactivation_delete', __( 'Deactivation', 'cookie-notice' ), array( $this, 'cn_deactivation_delete' ), 'cookie_notice_options', 'cookie_notice_configuration' );
293
- // compliance disabled
294
- } else {
295
- // configuration
296
- add_settings_section( 'cookie_notice_compliance', __( 'Compliance Settings', 'cookie-notice' ), array( $this, 'cn_section_compliance' ), 'cookie_notice_options' );
297
- add_settings_field( 'cn_app_status', __( 'Compliance status', 'cookie-notice' ), array( $this, 'cn_app_status' ), 'cookie_notice_options', 'cookie_notice_compliance' );
298
- add_settings_field( 'cn_app_id', __( 'App ID', 'cookie-notice' ), array( $this, 'cn_app_id' ), 'cookie_notice_options', 'cookie_notice_compliance' );
299
- add_settings_field( 'cn_app_key', __( 'App Key', 'cookie-notice' ), array( $this, 'cn_app_key' ), 'cookie_notice_options', 'cookie_notice_compliance' );
300
-
301
- add_settings_section( 'cookie_notice_configuration', __( 'Notice Settings', 'cookie-notice' ), array( $this, 'cn_section_configuration' ), 'cookie_notice_options' );
302
- add_settings_field( 'cn_message_text', __( 'Message', 'cookie-notice' ), array( $this, 'cn_message_text' ), 'cookie_notice_options', 'cookie_notice_configuration' );
303
- add_settings_field( 'cn_accept_text', __( 'Button text', 'cookie-notice' ), array( $this, 'cn_accept_text' ), 'cookie_notice_options', 'cookie_notice_configuration' );
304
- add_settings_field( 'cn_see_more', __( 'Privacy policy', 'cookie-notice' ), array( $this, 'cn_see_more' ), 'cookie_notice_options', 'cookie_notice_configuration' );
305
- add_settings_field( 'cn_refuse_opt', __( 'Refuse consent', 'cookie-notice' ), array( $this, 'cn_refuse_opt' ), 'cookie_notice_options', 'cookie_notice_configuration' );
306
- add_settings_field( 'cn_revoke_opt', __( 'Revoke consent', 'cookie-notice' ), array( $this, 'cn_revoke_opt' ), 'cookie_notice_options', 'cookie_notice_configuration' );
307
- add_settings_field( 'cn_refuse_code', __( 'Script blocking', 'cookie-notice' ), array( $this, 'cn_refuse_code' ), 'cookie_notice_options', 'cookie_notice_configuration' );
308
- add_settings_field( 'cn_redirection', __( 'Reloading', 'cookie-notice' ), array( $this, 'cn_redirection' ), 'cookie_notice_options', 'cookie_notice_configuration' );
309
- add_settings_field( 'cn_on_scroll', __( 'On scroll', 'cookie-notice' ), array( $this, 'cn_on_scroll' ), 'cookie_notice_options', 'cookie_notice_configuration' );
310
- add_settings_field( 'cn_on_click', __( 'On click', 'cookie-notice' ), array( $this, 'cn_on_click' ), 'cookie_notice_options', 'cookie_notice_configuration' );
311
- add_settings_field( 'cn_time', __( 'Accepted expiry', 'cookie-notice' ), array( $this, 'cn_time' ), 'cookie_notice_options', 'cookie_notice_configuration' );
312
- add_settings_field( 'cn_time_rejected', __( 'Rejected expiry', 'cookie-notice' ), array( $this, 'cn_time_rejected' ), 'cookie_notice_options', 'cookie_notice_configuration' );
313
- add_settings_field( 'cn_script_placement', __( 'Script placement', 'cookie-notice' ), array( $this, 'cn_script_placement' ), 'cookie_notice_options', 'cookie_notice_configuration' );
314
- add_settings_field( 'cn_deactivation_delete', __( 'Deactivation', 'cookie-notice' ), array( $this, 'cn_deactivation_delete' ), 'cookie_notice_options', 'cookie_notice_configuration' );
315
-
316
- // design
317
- add_settings_section( 'cookie_notice_design', __( 'Notice Design', 'cookie-notice' ), array( $this, 'cn_section_design' ), 'cookie_notice_options' );
318
- add_settings_field( 'cn_position', __( 'Position', 'cookie-notice' ), array( $this, 'cn_position' ), 'cookie_notice_options', 'cookie_notice_design' );
319
- add_settings_field( 'cn_hide_effect', __( 'Animation', 'cookie-notice' ), array( $this, 'cn_hide_effect' ), 'cookie_notice_options', 'cookie_notice_design' );
320
- add_settings_field( 'cn_colors', __( 'Colors', 'cookie-notice' ), array( $this, 'cn_colors' ), 'cookie_notice_options', 'cookie_notice_design' );
321
- add_settings_field( 'cn_css_class', __( 'Button class', 'cookie-notice' ), array( $this, 'cn_css_class' ), 'cookie_notice_options', 'cookie_notice_design' );
322
- }
323
- }
324
-
325
- /**
326
- * Section callback: fix for WP < 3.3
327
- */
328
- public function cn_section_configuration() {}
329
- public function cn_section_compliance() {}
330
- public function cn_section_design() {}
331
-
332
- /**
333
- * Compliance status.
334
- */
335
- public function cn_app_status() {
336
- $app_status = Cookie_Notice()->get_status();
337
-
338
- switch ( $app_status ) {
339
- case 'active':
340
- echo '
341
- <fieldset>
342
- <div id="cn_app_status">
343
- <span class="cn_compliance_status">' . __( 'Notice', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
344
- <span class="cn_compliance_status">' . __( 'Autoblocking', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
345
- <span class="cn_compliance_status">' . __( 'Cookie Categories', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
346
- <span class="cn_compliance_status">' . __( 'Proof-of-Consent', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
347
- </div>
348
- <div id="cn_app_actions">
349
- <a href="' . $this->app_login_url . '" class="button button-primary button-hero cn-button" target="_blank">' . __( 'Log in & Configure', 'cookie-notice' ) . '</a>
350
- <p class="description">' . __( 'Log into the Cookie Compliance&trade; web application and configure your Privacy Experience.', 'cookie-notice' ) . '</p>
351
- </div>
352
- </fieldset>';
353
- break;
354
- case 'pending':
355
- echo '
356
- <fieldset>
357
- <div id="cn_app_status">
358
- <span class="cn_compliance_status">' . __( 'Notice', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
359
- <span class="cn_compliance_status">' . __( 'Autoblocking', 'cookie-notice' ) . ': <label class="cn-pending">' . __( 'Pending', 'cookie-notice' ) . '</label></span>
360
- <span class="cn_compliance_status">' . __( 'Cookie Categories', 'cookie-notice' ) . ': <label class="cn-pending">' . __( 'Pending', 'cookie-notice' ) . '</label></span>
361
- <span class="cn_compliance_status">' . __( 'Proof-of-Consent', 'cookie-notice' ) . ': <label class="cn-pending">' . __( 'Pending', 'cookie-notice' ) . '</label></span>
362
- </div>
363
- <div id="cn_app_actions">
364
- <a href="' . $this->app_login_url . '" class="button button-primary button-hero cn-button" target="_blank">' . __( 'Log in & configure', 'cookie-notice' ) . '</a>
365
- <p class="description">' . __( 'Log into the Cookie Compliance&trade; web application and complete the setup process.', 'cookie-notice' ) . '</p>
366
- </div>
367
- </fieldset>';
368
- break;
369
- default:
370
- echo '
371
- <fieldset>
372
- <div id="cn_app_status">
373
- <span class="cn_compliance_status">' . __( 'Notice', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
374
- <span class="cn_compliance_status">' . __( 'Autoblocking', 'cookie-notice' ) . ': <label class="cn-inactive">' . __( 'Inactive', 'cookie-notice' ) . '</label></span>
375
- <span class="cn_compliance_status">' . __( 'Cookie Categories', 'cookie-notice' ) . ': <label class="cn-inactive">' . __( 'Inactive', 'cookie-notice' ) . '</label></span>
376
- <span class="cn_compliance_status">' . __( 'Proof-of-Consent', 'cookie-notice' ) . ': <label class="cn-inactive">' . __( 'Inactive', 'cookie-notice' ) . '</label></span>
377
- </div>
378
- <div id="cn_app_actions">
379
- <a href="' . admin_url( 'index.php?page=cookie-notice' ) . '" class="button button-primary button-hero cn-button cn-run-welcome">' . __( 'Add Compliance features', 'cookie-notice' ) . '</a>
380
- <p class="description">' . __( 'Sign up to Cookie Compliance&trade; and add GDPR, CCPA and other international data privacy laws compliance features.', 'cookie-notice' ) . '</p>
381
- </div>
382
- </fieldset>';
383
- break;
384
- }
385
- }
386
-
387
- /**
388
- * App welcome.
389
- */
390
- public function cn_app_id() {
391
- echo '
392
- <fieldset>
393
- <div id="cn_app_id">
394
- <input type="text" class="regular-text" name="cookie_notice_options[app_id]" value="' . esc_attr( Cookie_Notice()->options['general']['app_id'] ) . '" />
395
- <p class="description">' . __( 'Enter your Cookie Compliance&trade; application ID.', 'cookie-notice' ) . '</p>
396
- </div>
397
- </fieldset>';
398
- }
399
-
400
- /**
401
- * App ID option.
402
- */
403
- public function cn_app_key() {
404
- echo '
405
- <div id="cn_app_key">
406
- <input type="password" class="regular-text" name="cookie_notice_options[app_key]" value="' . esc_attr( Cookie_Notice()->options['general']['app_key'] ) . '" />
407
- <p class="description">' . __( 'Enter your Cookie Compliance&trade; application secret key.', 'cookie-notice' ) . '</p>
408
- </div>';
409
- }
410
-
411
- /**
412
- * App autoblocking.
413
- */
414
- public function cn_app_blocking() {
415
- echo '
416
- <fieldset>
417
- <label for="cn_app_blocking"><input id="cn_app_blocking" type="checkbox" name="cookie_notice_options[app_blocking]" value="1" ' . checked( true, Cookie_Notice()->options['general']['app_blocking'], false ) . ' />' . __( 'Enable to automatically block 3rd party scripts before user consent.', 'cookie-notice' ) . '</label>
418
- <p class="description">' . __( "In case you're experiencing issues with your site disable that feature temporarily.", 'cookie-notice' ) . '</p>
419
- </fieldset>';
420
- }
421
-
422
- /**
423
- * App ID option.
424
- */
425
- public function cn_app_purge_cache() {
426
- echo '
427
- <div id="cn_app_purge_cache">
428
- <div class="cn-button-container">
429
- <a href="#" class="button button-secondary">' . __( 'Purge Cache', 'cookie-notice' ) . '</a>
430
- </div>
431
- <p class="description">' . __( 'Click the Purge Cache button to refresh the app configuration.', 'cookie-notice' ) . '</p>
432
- </div>';
433
- }
434
-
435
- /**
436
- * Hide banner.
437
- */
438
- public function cn_hide_banner() {
439
- echo '
440
- <fieldset>
441
- <label for="cn_hide_banner"><input id="cn_hide_banner" type="checkbox" name="cookie_notice_options[hide_banner]" value="1" ' . checked( true, Cookie_Notice()->options['general']['hide_banner'], false ) . ' />' . __( 'Enable to hide the consent banner for logged in users.', 'cookie-notice' ) . '</label>
442
- </fieldset>';
443
- }
444
-
445
- /**
446
- * Debug mode.
447
- */
448
- public function cn_debug_mode() {
449
- echo '
450
- <fieldset>
451
- <label for="cn_debug_mode"><input id="cn_debug_mode" type="checkbox" name="cookie_notice_options[debug_mode]" value="1" ' . checked( true, Cookie_Notice()->options['general']['debug_mode'], false ) . ' />' . __( 'Enable to run the consent banner in debug mode.', 'cookie-notice' ) . '</label>
452
- </fieldset>';
453
- }
454
-
455
- /**
456
- * App Key option.
457
- */
458
- public function cn_message_text() {
459
- echo '
460
- <div id="cn_message_text">
461
- <textarea name="cookie_notice_options[message_text]" class="large-text" cols="50" rows="5">' . esc_textarea( Cookie_Notice()->options['general']['message_text'] ) . '</textarea>
462
- <p class="description">' . __( 'Enter the cookie notice message.', 'cookie-notice' ) . '</p>
463
- </div>';
464
- }
465
-
466
- /**
467
- * Accept cookie label option.
468
- */
469
- public function cn_accept_text() {
470
- echo '
471
- <div id="cn_accept_text">
472
- <input type="text" class="regular-text" name="cookie_notice_options[accept_text]" value="' . esc_attr( Cookie_Notice()->options['general']['accept_text'] ) . '" />
473
- <p class="description">' . __( 'The text of the option to accept the notice and make it disappear.', 'cookie-notice' ) . '</p>
474
- </div>';
475
- }
476
-
477
- /**
478
- * Enable/Disable third party non functional cookies option.
479
- */
480
- public function cn_refuse_opt() {
481
- echo '
482
- <fieldset>
483
- <label><input id="cn_refuse_opt" type="checkbox" name="cookie_notice_options[refuse_opt]" value="1" ' . checked( true, Cookie_Notice()->options['general']['refuse_opt'], false ) . ' />' . __( 'Enable to give to the user the possibility to refuse third party non functional cookies.', 'cookie-notice' ) . '</label>
484
- <div id="cn_refuse_opt_container"' . ( Cookie_Notice()->options['general']['refuse_opt'] === false ? ' style="display: none;"' : '' ) . '>
485
- <div id="cn_refuse_text">
486
- <input type="text" class="regular-text" name="cookie_notice_options[refuse_text]" value="' . esc_attr( Cookie_Notice()->options['general']['refuse_text'] ) . '" />
487
- <p class="description">' . __( 'The text of the button to refuse the consent.', 'cookie-notice' ) . '</p>
488
- </div>
489
- </div>
490
- </fieldset>';
491
- }
492
-
493
- /**
494
- * Non functional cookies code.
495
- */
496
- public function cn_refuse_code() {
497
- $allowed_html = Cookie_Notice()->get_allowed_html();
498
- $active = ! empty( Cookie_Notice()->options['general']['refuse_code'] ) && empty( Cookie_Notice()->options['general']['refuse_code_head'] ) ? 'body' : 'head';
499
-
500
- echo '
501
- <fieldset>
502
- <div id="cn_refuse_code">
503
- <div id="cn_refuse_code_fields">
504
- <h2 class="nav-tab-wrapper">
505
- <a id="refuse_head-tab" class="nav-tab' . ( $active === 'head' ? ' nav-tab-active' : '' ) . '" href="#refuse_head">' . __( 'Head', 'cookie-notice' ) . '</a>
506
- <a id="refuse_body-tab" class="nav-tab' . ( $active === 'body' ? ' nav-tab-active' : '' ) . '" href="#refuse_body">' . __( 'Body', 'cookie-notice' ) . '</a>
507
- </h2>
508
- <div id="refuse_head" class="refuse-code-tab' . ( $active === 'head' ? ' active' : '' ) . '">
509
- <p class="description">' . __( 'The code to be used in your site header, before the closing head tag.', 'cookie-notice' ) . '</p>
510
- <textarea name="cookie_notice_options[refuse_code_head]" class="large-text" cols="50" rows="8">' . html_entity_decode( trim( wp_kses( Cookie_Notice()->options['general']['refuse_code_head'], $allowed_html ) ) ) . '</textarea>
511
- </div>
512
- <div id="refuse_body" class="refuse-code-tab' . ( $active === 'body' ? ' active' : '' ) . '">
513
- <p class="description">' . __( 'The code to be used in your site footer, before the closing body tag.', 'cookie-notice' ) . '</p>
514
- <textarea name="cookie_notice_options[refuse_code]" class="large-text" cols="50" rows="8">' . html_entity_decode( trim( wp_kses( Cookie_Notice()->options['general']['refuse_code'], $allowed_html ) ) ) . '</textarea>
515
- </div>
516
- </div>
517
- <p class="description">' . __( 'Enter non functional cookies Javascript code here (for e.g. Google Analitycs) to be used after the notice is accepted.', 'cookie-notice' ) . '</br>' . __( 'To get the user consent status use the <code>cn_cookies_accepted()</code> function.', 'cookie-notice' ) . '</p>
518
- </div>
519
- </fieldset>';
520
- }
521
-
522
- /**
523
- * Revoke cookies option.
524
- */
525
- public function cn_revoke_opt() {
526
- echo '
527
- <fieldset>
528
- <label><input id="cn_revoke_cookies" type="checkbox" name="cookie_notice_options[revoke_cookies]" value="1" ' . checked( true, Cookie_Notice()->options['general']['revoke_cookies'], false ) . ' />' . __( 'Enable to give to the user the possibility to revoke their consent <i>(requires "Refuse consent" option enabled)</i>.', 'cookie-notice' ) . '</label>
529
- <div id="cn_revoke_opt_container"' . ( Cookie_Notice()->options['general']['revoke_cookies'] ? '' : ' style="display: none;"' ) . '>
530
- <textarea name="cookie_notice_options[revoke_message_text]" class="large-text" cols="50" rows="2">' . esc_textarea( Cookie_Notice()->options['general']['revoke_message_text'] ) . '</textarea>
531
- <p class="description">' . __( 'Enter the revoke message.', 'cookie-notice' ) . '</p>
532
- <input type="text" class="regular-text" name="cookie_notice_options[revoke_text]" value="' . esc_attr( Cookie_Notice()->options['general']['revoke_text'] ) . '" />
533
- <p class="description">' . __( 'The text of the button to revoke the consent.', 'cookie-notice' ) . '</p>';
534
-
535
- foreach ( $this->revoke_opts as $value => $label ) {
536
- echo '
537
- <label><input id="cn_revoke_cookies-' . $value . '" type="radio" name="cookie_notice_options[revoke_cookies_opt]" value="' . $value . '" ' . checked( $value, Cookie_Notice()->options['general']['revoke_cookies_opt'], false ) . ' />' . esc_html( $label ) . '</label>';
538
- }
539
-
540
- echo '
541
- <p class="description">' . __( 'Select the method for displaying the revoke button - automatic (in the banner) or manual using <code>[cookies_revoke]</code> shortcode.', 'cookie-notice' ) . '</p>
542
- </div>
543
- </fieldset>';
544
- }
545
-
546
- /**
547
- * Redirection on cookie accept.
548
- */
549
- public function cn_redirection() {
550
- echo '
551
- <fieldset>
552
- <label><input id="cn_redirection" type="checkbox" name="cookie_notice_options[redirection]" value="1" ' . checked( true, Cookie_Notice()->options['general']['redirection'], false ) . ' />' . __( 'Enable to reload the page after the notice is accepted.', 'cookie-notice' ) . '</label>
553
- </fieldset>';
554
- }
555
-
556
- /**
557
- * Privacy policy link option.
558
- */
559
- public function cn_see_more() {
560
- $pages = get_pages(
561
- array(
562
- 'sort_order' => 'ASC',
563
- 'sort_column' => 'post_title',
564
- 'hierarchical' => 0,
565
- 'child_of' => 0,
566
- 'parent' => -1,
567
- 'offset' => 0,
568
- 'post_type' => 'page',
569
- 'post_status' => 'publish'
570
- )
571
- );
572
-
573
- echo '
574
- <fieldset>
575
- <label><input id="cn_see_more" type="checkbox" name="cookie_notice_options[see_more]" value="1" ' . checked( true, Cookie_Notice()->options['general']['see_more'], false ) . ' />' . __( 'Enable privacy policy link.', 'cookie-notice' ) . '</label>
576
- <div id="cn_see_more_opt"' . (Cookie_Notice()->options['general']['see_more'] === false ? ' style="display: none;"' : '') . '>
577
- <input type="text" class="regular-text" name="cookie_notice_options[see_more_opt][text]" value="' . esc_attr( Cookie_Notice()->options['general']['see_more_opt']['text'] ) . '" />
578
- <p class="description">' . __( 'The text of the privacy policy button.', 'cookie-notice' ) . '</p>
579
- <div id="cn_see_more_opt_custom_link">';
580
-
581
- foreach ( $this->links as $value => $label ) {
582
- $value = esc_attr( $value );
583
-
584
- echo '
585
- <label><input id="cn_see_more_link-' . $value . '" type="radio" name="cookie_notice_options[see_more_opt][link_type]" value="' . $value . '" ' . checked( $value, Cookie_Notice()->options['general']['see_more_opt']['link_type'], false ) . ' />' . esc_html( $label ) . '</label>';
586
- }
587
-
588
- echo '
589
- </div>
590
- <p class="description">' . __( 'Select where to redirect user for more information.', 'cookie-notice' ) . '</p>
591
- <div id="cn_see_more_opt_page"' . (Cookie_Notice()->options['general']['see_more_opt']['link_type'] === 'custom' ? ' style="display: none;"' : '') . '>
592
- <select name="cookie_notice_options[see_more_opt][id]">
593
- <option value="0" ' . selected( 0, Cookie_Notice()->options['general']['see_more_opt']['id'], false ) . '>' . __( '-- select page --', 'cookie-notice' ) . '</option>';
594
-
595
- if ( $pages ) {
596
- foreach ( $pages as $page ) {
597
- echo '
598
- <option value="' . $page->ID . '" ' . selected( $page->ID, Cookie_Notice()->options['general']['see_more_opt']['id'], false ) . '>' . esc_html( $page->post_title ) . '</option>';
599
- }
600
- }
601
-
602
- echo '
603
- </select>
604
- <p class="description">' . __( 'Select from one of your site\'s pages.', 'cookie-notice' ) . '</p>';
605
-
606
- global $wp_version;
607
-
608
- if ( version_compare( $wp_version, '4.9.6', '>=' ) ) {
609
- echo '
610
- <label><input id="cn_see_more_opt_sync" type="checkbox" name="cookie_notice_options[see_more_opt][sync]" value="1" ' . checked( true, Cookie_Notice()->options['general']['see_more_opt']['sync'], false ) . ' />' . __( 'Synchronize with WordPress Privacy Policy page.', 'cookie-notice' ) . '</label>';
611
- }
612
-
613
- echo '
614
- </div>
615
- <div id="cn_see_more_opt_link"' . (Cookie_Notice()->options['general']['see_more_opt']['link_type'] === 'page' ? ' style="display: none;"' : '') . '>
616
- <input type="text" class="regular-text" name="cookie_notice_options[see_more_opt][link]" value="' . esc_attr( Cookie_Notice()->options['general']['see_more_opt']['link'] ) . '" />
617
- <p class="description">' . __( 'Enter the full URL starting with http(s)://', 'cookie-notice' ) . '</p>
618
- </div>
619
- <div id="cn_see_more_link_target">';
620
-
621
- foreach ( $this->link_targets as $target ) {
622
- echo '
623
- <label><input id="cn_see_more_link_target-' . $target . '" type="radio" name="cookie_notice_options[link_target]" value="' . $target . '" ' . checked( $target, Cookie_Notice()->options['general']['link_target'], false ) . ' />' . $target . '</label>';
624
- }
625
-
626
- echo '
627
- <p class="description">' . esc_html__( 'Select the privacy policy link target.', 'cookie-notice' ) . '</p>
628
- </div>
629
- <div id="cn_see_more_link_position">';
630
-
631
- foreach ( $this->link_positions as $position => $label ) {
632
- echo '
633
- <label><input id="cn_see_more_link_position-' . $position . '" type="radio" name="cookie_notice_options[link_position]" value="' . $position . '" ' . checked( $position, Cookie_Notice()->options['general']['link_position'], false ) . ' />' . esc_html( $label ) . '</label>';
634
- }
635
-
636
- echo '
637
- <p class="description">' . esc_html__( 'Select the privacy policy link position.', 'cookie-notice' ) . '</p>
638
- </div></div>
639
- </fieldset>';
640
- }
641
-
642
- /**
643
- * Expiration time option.
644
- */
645
- public function cn_time() {
646
- echo '
647
- <fieldset>
648
- <div id="cn_time">
649
- <select name="cookie_notice_options[time]">';
650
-
651
- foreach ( $this->times as $time => $arr ) {
652
- $time = esc_attr( $time );
653
-
654
- echo '
655
- <option value="' . $time . '" ' . selected( $time, Cookie_Notice()->options['general']['time'] ) . '>' . esc_html( $arr[0] ) . '</option>';
656
- }
657
-
658
- echo '
659
- </select>
660
- <p class="description">' . __( 'The amount of time that the cookie should be stored for when user accepts the notice.', 'cookie-notice' ) . '</p>
661
- </div>
662
- </fieldset>';
663
- }
664
-
665
- /**
666
- * Expiration time option.
667
- */
668
- public function cn_time_rejected() {
669
- echo '
670
- <fieldset>
671
- <div id="cn_time_rejected">
672
- <select name="cookie_notice_options[time_rejected]">';
673
-
674
- foreach ( $this->times as $time => $arr ) {
675
- $time = esc_attr( $time );
676
-
677
- echo '
678
- <option value="' . $time . '" ' . selected( $time, Cookie_Notice()->options['general']['time_rejected'] ) . '>' . esc_html( $arr[0] ) . '</option>';
679
- }
680
-
681
- echo '
682
- </select>
683
- <p class="description">' . __( 'The amount of time that the cookie should be stored for when the user doesn\'t accept the notice.', 'cookie-notice' ) . '</p>
684
- </div>
685
- </fieldset>';
686
- }
687
-
688
- /**
689
- * Script placement option.
690
- */
691
- public function cn_script_placement() {
692
- echo '
693
- <fieldset>';
694
-
695
- foreach ( $this->script_placements as $value => $label ) {
696
- echo '
697
- <label><input id="cn_script_placement-' . $value . '" type="radio" name="cookie_notice_options[script_placement]" value="' . esc_attr( $value ) . '" ' . checked( $value, Cookie_Notice()->options['general']['script_placement'], false ) . ' />' . esc_html( $label ) . '</label>';
698
- }
699
-
700
- echo '
701
- <p class="description">' . __( 'Select where all the plugin scripts should be placed.', 'cookie-notice' ) . '</p>
702
- </fieldset>';
703
- }
704
-
705
- /**
706
- * Position option.
707
- */
708
- public function cn_position() {
709
- echo '
710
- <fieldset>
711
- <div id="cn_position">';
712
-
713
- foreach ( $this->positions as $value => $label ) {
714
- $value = esc_attr( $value );
715
-
716
- echo '
717
- <label><input id="cn_position-' . $value . '" type="radio" name="cookie_notice_options[position]" value="' . $value . '" ' . checked( $value, Cookie_Notice()->options['general']['position'], false ) . ' />' . esc_html( $label ) . '</label>';
718
- }
719
-
720
- echo '
721
- <p class="description">' . __( 'Select location for the notice.', 'cookie-notice' ) . '</p>
722
- </div>
723
- </fieldset>';
724
- }
725
-
726
- /**
727
- * Animation effect option.
728
- */
729
- public function cn_hide_effect() {
730
- echo '
731
- <fieldset>
732
- <div id="cn_hide_effect">';
733
-
734
- foreach ( $this->effects as $value => $label ) {
735
- $value = esc_attr( $value );
736
-
737
- echo '
738
- <label><input id="cn_hide_effect-' . $value . '" type="radio" name="cookie_notice_options[hide_effect]" value="' . $value . '" ' . checked( $value, Cookie_Notice()->options['general']['hide_effect'], false ) . ' />' . esc_html( $label ) . '</label>';
739
- }
740
-
741
- echo '
742
- <p class="description">' . __( 'Select the animation style.', 'cookie-notice' ) . '</p>
743
- </div>
744
- </fieldset>';
745
- }
746
-
747
- /**
748
- * On scroll option.
749
- */
750
- public function cn_on_scroll() {
751
- echo '
752
- <fieldset>
753
- <label><input id="cn_on_scroll" type="checkbox" name="cookie_notice_options[on_scroll]" value="1" ' . checked( true, Cookie_Notice()->options['general']['on_scroll'], false ) . ' />' . __( 'Enable to accept the notice when user scrolls.', 'cookie-notice' ) . '</label>
754
- <div id="cn_on_scroll_offset"' . ( Cookie_Notice()->options['general']['on_scroll'] === false || Cookie_Notice()->options['general']['on_scroll'] == false ? ' style="display: none;"' : '' ) . '>
755
- <input type="text" class="text" name="cookie_notice_options[on_scroll_offset]" value="' . esc_attr( Cookie_Notice()->options['general']['on_scroll_offset'] ) . '" /> <span>px</span>
756
- <p class="description">' . __( 'Number of pixels user has to scroll to accept the notice and make it disappear.', 'cookie-notice' ) . '</p>
757
- </div>
758
- </fieldset>';
759
- }
760
-
761
- /**
762
- * On click option.
763
- */
764
- public function cn_on_click() {
765
- echo '
766
- <fieldset>
767
- <label><input id="cn_on_click" type="checkbox" name="cookie_notice_options[on_click]" value="1" ' . checked( true, Cookie_Notice()->options['general']['on_click'], false ) . ' />' . __( 'Enable to accept the notice on any click on the page.', 'cookie-notice' ) . '</label>
768
- </fieldset>';
769
- }
770
-
771
- /**
772
- * Delete plugin data on deactivation.
773
- */
774
- public function cn_deactivation_delete() {
775
- echo '
776
- <fieldset>
777
- <label><input id="cn_deactivation_delete" type="checkbox" name="cookie_notice_options[deactivation_delete]" value="1" ' . checked( true, Cookie_Notice()->options['general']['deactivation_delete'], false ) . '/>' . __( 'Enable if you want all plugin data to be deleted on deactivation.', 'cookie-notice' ) . '</label>
778
- </fieldset>';
779
- }
780
-
781
- /**
782
- * CSS style option.
783
- */
784
- public function cn_css_class() {
785
- echo '
786
- <fieldset>
787
- <div id="cn_css_class">
788
- <input type="text" class="regular-text" name="cookie_notice_options[css_class]" value="' . esc_attr( Cookie_Notice()->options['general']['css_class'] ) . '" />
789
- <p class="description">' . __( 'Enter additional button CSS classes separated by spaces.', 'cookie-notice' ) . '</p>
790
- </div>
791
- </fieldset>';
792
- }
793
-
794
- /**
795
- * Colors option.
796
- */
797
- public function cn_colors() {
798
- echo '
799
- <fieldset>';
800
-
801
- foreach ( $this->colors as $value => $label ) {
802
- $value = esc_attr( $value );
803
-
804
- echo '
805
- <div id="cn_colors-' . $value . '"><label>' . esc_html( $label ) . '</label><br />
806
- <input class="cn_color" type="text" name="cookie_notice_options[colors][' . $value . ']" value="' . esc_attr( Cookie_Notice()->options['general']['colors'][$value] ) . '" />' .
807
- '</div>';
808
- }
809
-
810
- // print_r( Cookie_Notice()->options['general']['colors'] );
811
-
812
- echo '
813
- <div id="cn_colors-bar_opacity"><label>' . __( 'Bar opacity', 'cookie-notice' ) . '</label><br />
814
- <div><input id="cn_colors_bar_opacity_range" class="cn_range" type="range" min="50" max="100" step="1" name="cookie_notice_options[colors][bar_opacity]" value="' . absint( Cookie_Notice()->options['general']['colors']['bar_opacity'] ) . '" onchange="cn_colors_bar_opacity_text.value = cn_colors_bar_opacity_range.value" /><input id="cn_colors_bar_opacity_text" class="small-text" type="number" onchange="cn_colors_bar_opacity_range.value = cn_colors_bar_opacity_text.value" min="50" max="100" value="' . absint( Cookie_Notice()->options['general']['colors']['bar_opacity'] ) . '" /></div>' .
815
- '</div>';
816
-
817
- echo '
818
- </fieldset>';
819
- }
820
-
821
- /**
822
- * Validate options.
823
- *
824
- * @param array $input
825
- * @return array
826
- */
827
- public function validate_options( $input ) {
828
- if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
829
- return $input;
830
-
831
- // get main instance
832
- $cn = Cookie_Notice();
833
-
834
- if ( isset( $_POST['save_cookie_notice_options'] ) ) {
835
- // app id
836
- $input['app_id'] = sanitize_text_field( isset( $input['app_id'] ) ? $input['app_id'] : $cn->defaults['general']['app_id'] );
837
-
838
- // app key
839
- $input['app_key'] = sanitize_text_field( isset( $input['app_key'] ) ? $input['app_key'] : $cn->defaults['general']['app_key'] );
840
-
841
- // set app status
842
- if ( ! empty( $input['app_id'] ) && ! empty( $input['app_key'] ) ) {
843
- $app_status = esc_attr( $cn->welcome_api->get_app_status( $input['app_id'] ) );
844
-
845
- update_option( 'cookie_notice_status', $app_status );
846
- } else {
847
- update_option( 'cookie_notice_status', '' );
848
- }
849
-
850
- // app blocking
851
- $input['app_blocking'] = (bool) isset( $input['app_blocking'] );
852
-
853
- // hide banner
854
- $input['hide_banner'] = (bool) isset( $input['hide_banner'] );
855
-
856
- // debug mode
857
- $input['debug_mode'] = (bool) isset( $input['debug_mode'] );
858
-
859
- // position
860
- $input['position'] = sanitize_text_field( isset( $input['position'] ) && in_array( $input['position'], array_keys( $this->positions ) ) ? $input['position'] : $cn->defaults['general']['position'] );
861
-
862
- // colors
863
- $input['colors']['text'] = sanitize_text_field( isset( $input['colors']['text'] ) && $input['colors']['text'] !== '' && preg_match( '/^#[a-f0-9]{6}$/', $input['colors']['text'] ) === 1 ? $input['colors']['text'] : $cn->defaults['general']['colors']['text'] );
864
- $input['colors']['button'] = sanitize_text_field( isset( $input['colors']['button'] ) && $input['colors']['button'] !== '' && preg_match( '/^#[a-f0-9]{6}$/', $input['colors']['button'] ) === 1 ? $input['colors']['button'] : $cn->defaults['general']['colors']['button'] );
865
- $input['colors']['bar'] = sanitize_text_field( isset( $input['colors']['bar'] ) && $input['colors']['bar'] !== '' && preg_match( '/^#[a-f0-9]{6}$/', $input['colors']['bar'] ) === 1 ? $input['colors']['bar'] : $cn->defaults['general']['colors']['bar'] );
866
- $input['colors']['bar_opacity'] = absint( isset( $input['colors']['bar_opacity'] ) && $input['colors']['bar_opacity'] >= 50 ? $input['colors']['bar_opacity'] : $cn->defaults['general']['colors']['bar_opacity'] );
867
-
868
- // texts
869
- $input['message_text'] = wp_kses_post( isset( $input['message_text'] ) && $input['message_text'] !== '' ? $input['message_text'] : $cn->defaults['general']['message_text'] );
870
- $input['accept_text'] = sanitize_text_field( isset( $input['accept_text'] ) && $input['accept_text'] !== '' ? $input['accept_text'] : $cn->defaults['general']['accept_text'] );
871
- $input['refuse_text'] = sanitize_text_field( isset( $input['refuse_text'] ) && $input['refuse_text'] !== '' ? $input['refuse_text'] : $cn->defaults['general']['refuse_text'] );
872
- $input['revoke_message_text'] = wp_kses_post( isset( $input['revoke_message_text'] ) && $input['revoke_message_text'] !== '' ? $input['revoke_message_text'] : $cn->defaults['general']['revoke_message_text'] );
873
- $input['revoke_text'] = sanitize_text_field( isset( $input['revoke_text'] ) && $input['revoke_text'] !== '' ? $input['revoke_text'] : $cn->defaults['general']['revoke_text'] );
874
- $input['refuse_opt'] = (bool) isset( $input['refuse_opt'] );
875
- $input['revoke_cookies'] = isset( $input['revoke_cookies'] );
876
- $input['revoke_cookies_opt'] = isset( $input['revoke_cookies_opt'] ) && array_key_exists( $input['revoke_cookies_opt'], $this->revoke_opts ) ? $input['revoke_cookies_opt'] : $cn->defaults['general']['revoke_cookies_opt'];
877
-
878
- // get allowed HTML
879
- $allowed_html = $cn->get_allowed_html();
880
-
881
- // body refuse code
882
- $input['refuse_code'] = wp_kses( isset( $input['refuse_code'] ) && $input['refuse_code'] !== '' ? $input['refuse_code'] : $cn->defaults['general']['refuse_code'], $allowed_html );
883
-
884
- // head refuse code
885
- $input['refuse_code_head'] = wp_kses( isset( $input['refuse_code_head'] ) && $input['refuse_code_head'] !== '' ? $input['refuse_code_head'] : $cn->defaults['general']['refuse_code_head'], $allowed_html );
886
-
887
- // css button class
888
- $input['css_class'] = sanitize_text_field( isset( $input['css_class'] ) ? $input['css_class'] : $cn->defaults['general']['css_class'] );
889
-
890
- // link target
891
- $input['link_target'] = sanitize_text_field( isset( $input['link_target'] ) && in_array( $input['link_target'], array_keys( $this->link_targets ) ) ? $input['link_target'] : $cn->defaults['general']['link_target'] );
892
-
893
- // time
894
- $input['time'] = sanitize_text_field( isset( $input['time'] ) && in_array( $input['time'], array_keys( $this->times ) ) ? $input['time'] : $cn->defaults['general']['time'] );
895
- $input['time_rejected'] = sanitize_text_field( isset( $input['time_rejected'] ) && in_array( $input['time_rejected'], array_keys( $this->times ) ) ? $input['time_rejected'] : $cn->defaults['general']['time_rejected'] );
896
-
897
- // script placement
898
- $input['script_placement'] = sanitize_text_field( isset( $input['script_placement'] ) && in_array( $input['script_placement'], array_keys( $this->script_placements ) ) ? $input['script_placement'] : $cn->defaults['general']['script_placement'] );
899
-
900
- // hide effect
901
- $input['hide_effect'] = sanitize_text_field( isset( $input['hide_effect'] ) && in_array( $input['hide_effect'], array_keys( $this->effects ) ) ? $input['hide_effect'] : $cn->defaults['general']['hide_effect'] );
902
-
903
- // redirection
904
- $input['redirection'] = isset( $input['redirection'] );
905
-
906
- // on scroll
907
- $input['on_scroll'] = isset( $input['on_scroll'] );
908
-
909
- // on scroll offset
910
- $input['on_scroll_offset'] = absint( isset( $input['on_scroll_offset'] ) && $input['on_scroll_offset'] !== '' ? $input['on_scroll_offset'] : $cn->defaults['general']['on_scroll_offset'] );
911
-
912
- // on click
913
- $input['on_click'] = isset( $input['on_click'] );
914
-
915
- // deactivation
916
- $input['deactivation_delete'] = isset( $input['deactivation_delete'] );
917
-
918
- // privacy policy
919
- $input['see_more'] = isset( $input['see_more'] );
920
- $input['see_more_opt']['text'] = sanitize_text_field( isset( $input['see_more_opt']['text'] ) && $input['see_more_opt']['text'] !== '' ? $input['see_more_opt']['text'] : $cn->defaults['general']['see_more_opt']['text'] );
921
- $input['see_more_opt']['link_type'] = sanitize_text_field( isset( $input['see_more_opt']['link_type'] ) && in_array( $input['see_more_opt']['link_type'], array_keys( $this->links ) ) ? $input['see_more_opt']['link_type'] : $cn->defaults['general']['see_more_opt']['link_type'] );
922
-
923
- if ( $input['see_more_opt']['link_type'] === 'custom' )
924
- $input['see_more_opt']['link'] = ( $input['see_more'] === true ? esc_url( $input['see_more_opt']['link'] ) : '' );
925
- elseif ( $input['see_more_opt']['link_type'] === 'page' ) {
926
- $input['see_more_opt']['id'] = ( $input['see_more'] === true ? (int) $input['see_more_opt']['id'] : 0 );
927
- $input['see_more_opt']['sync'] = isset( $input['see_more_opt']['sync'] );
928
-
929
- if ( $input['see_more_opt']['sync'] )
930
- update_option( 'wp_page_for_privacy_policy', $input['see_more_opt']['id'] );
931
- }
932
-
933
- // policy link position
934
- $input['link_position'] = sanitize_text_field( isset( $input['link_position'] ) && in_array( $input['link_position'], array_keys( $this->link_positions ) ) ? $input['link_position'] : $cn->defaults['general']['link_position'] );
935
-
936
- // message link position?
937
- if ( $input['see_more'] === true && $input['link_position'] === 'message' && strpos( $input['message_text'], '[cookies_policy_link' ) === false )
938
- $input['message_text'] .= ' [cookies_policy_link]';
939
-
940
- $input['update_version'] = $cn->options['general']['update_version'];
941
- $input['update_notice'] = $cn->options['general']['update_notice'];
942
-
943
- $input['translate'] = false;
944
-
945
- // WPML >= 3.2
946
- if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
947
- do_action( 'wpml_register_single_string', 'Cookie Notice', 'Message in the notice', $input['message_text'] );
948
- do_action( 'wpml_register_single_string', 'Cookie Notice', 'Button text', $input['accept_text'] );
949
- do_action( 'wpml_register_single_string', 'Cookie Notice', 'Refuse button text', $input['refuse_text'] );
950
- do_action( 'wpml_register_single_string', 'Cookie Notice', 'Revoke message text', $input['revoke_message_text'] );
951
- do_action( 'wpml_register_single_string', 'Cookie Notice', 'Revoke button text', $input['revoke_text'] );
952
- do_action( 'wpml_register_single_string', 'Cookie Notice', 'Privacy policy text', $input['see_more_opt']['text'] );
953
-
954
- if ( $input['see_more_opt']['link_type'] === 'custom' )
955
- do_action( 'wpml_register_single_string', 'Cookie Notice', 'Custom link', $input['see_more_opt']['link'] );
956
- }
957
-
958
- add_settings_error( 'cn_cookie_notice_options', 'save_cookie_notice_options', __( 'Settings saved.', 'iubenda' ), 'updated' );
959
-
960
- // purge cache on save
961
- delete_transient( 'cookie_notice_compliance_cache' );
962
- } elseif ( isset( $_POST['reset_cookie_notice_options'] ) ) {
963
- $input = $cn->defaults['general'];
964
-
965
- add_settings_error( 'cn_cookie_notice_options', 'reset_cookie_notice_options', __( 'Settings restored to defaults.', 'cookie-notice' ), 'updated' );
966
-
967
- // set app status
968
- update_option( 'cookie_notice_status', '' );
969
-
970
- // purge cache on save
971
- delete_transient( 'cookie_notice_compliance_cache' );
972
- }
973
-
974
- return $input;
975
- }
976
-
977
- /**
978
- * Load scripts and styles - admin.
979
- */
980
- public function admin_enqueue_scripts( $page ) {
981
- if ( $page === 'toplevel_page_cookie-notice' ) {
982
- wp_enqueue_script(
983
- 'cookie-notice-admin', plugins_url( '../js/admin' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', __FILE__ ), array( 'jquery', 'wp-color-picker' ), Cookie_Notice()->defaults['version']
984
- );
985
-
986
- wp_localize_script(
987
- 'cookie-notice-admin', 'cnArgs', array(
988
- 'ajaxURL' => admin_url( 'admin-ajax.php' ),
989
- 'nonce' => wp_create_nonce( 'cn-purge-cache' ),
990
- 'resetToDefaults' => __( 'Are you sure you want to reset these settings to defaults?', 'cookie-notice' )
991
- )
992
- );
993
-
994
- wp_enqueue_style( 'wp-color-picker' );
995
- wp_enqueue_style( 'cookie-notice-admin', plugins_url( '../css/admin' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', __FILE__ ) );
996
- }
997
- }
998
-
999
- /**
1000
- * Load admin style inline, for menu icon only.
1001
- *
1002
- * @return mixed
1003
- */
1004
- public function admin_print_styles() {
1005
- echo '
1006
- <style>
1007
- a.toplevel_page_cookie-notice .wp-menu-image {
1008
- background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAzMjEgMzIxIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zOnNlcmlmPSJodHRwOi8vd3d3LnNlcmlmLmNvbS8iIHN0eWxlPSJmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MjsiPjxwYXRoIGQ9Ik0zMTcuMjc4LDEzMC40NTFjLTAuODEyLC00LjMwMiAtNC4zMDEsLTcuNTYyIC04LjY0MiwtOC4wODFjLTQuMzU0LC0wLjUyMiAtOC41MDYsMS44MjkgLTEwLjMwNyw1LjgyMmMtMy4xNyw3LjAwMyAtMTAuMTMzLDExLjg3MyAtMTguMjA1LDExLjg2NGMtOC45NTUsMC4wMjIgLTE2LjUxNywtNi4wMjEgLTE5LjAzOCwtMTQuMzE1Yy0xLjUyMSwtNS4wNjMgLTYuNzI0LC04LjA2NCAtMTEuODY1LC02Ljg2M2MtMy4xNjMsMC43NDEgLTYuMTU0LDEuMTcyIC05LjEyNSwxLjE3MmMtMjIuMDM5LC0wLjA0MyAtMzkuOTc2LC0xNy45NzkgLTQwLjAxNSwtNDAuMDE5Yy0wLC0yLjk3IDAuNDMsLTUuOTYyIDEuMTY5LC05LjExM2MxLjIxMiwtNS4xNDEgLTEuNzk5LC0xMC4zNTMgLTYuODYsLTExLjg3M2MtOC4yOTUsLTIuNTEzIC0xNC4zMzcsLTEwLjA3NSAtMTQuMzE5LC0xOS4wMjljLTAuMDA5LC04LjA4MiA0Ljg2NCwtMTUuMDM2IDExLjg2NywtMTguMjA4YzMuOTkxLC0xLjc5OCA2LjM0MSwtNS45NjMgNS44MjIsLTEwLjMwNGMtMC41MjIsLTQuMzUxIC0zLjc4MywtNy44NDMgLTguMDg0LC04LjY1MmMtOS41NDMsLTEuNzkyIC0xOS40MjYsLTIuODUyIC0yOS42MTEsLTIuODUyYy04OC4yOTUsMC4wMjIgLTE2MC4wNDMsNzEuNzcgLTE2MC4wNjUsMTYwLjA2NWMwLjAyMiw4OC4yOTUgNzEuNzcsMTYwLjA0MyAxNjAuMDY1LDE2MC4wNjVjODguMjk1LC0wLjAyMiAxNjAuMDQzLC03MS43NyAxNjAuMDY1LC0xNjAuMDY1Yy0wLC0xMC4xODQgLTEuMDYzLC0yMC4wNjcgLTIuODUyLC0yOS42MTRabS01OC4yMjMsMTI4LjYwNGMtMjUuNDAxLDI1LjM4IC02MC4zNTUsNDEuMDY2IC05OC45OSw0MS4wNjZjLTM4LjYzNSwwIC03My41ODgsLTE1LjY4NiAtOTguOTg5LC00MS4wNjZjLTI1LjM4LC0yNS40MDEgLTQxLjA2NiwtNjAuMzU1IC00MS4wNjYsLTk4Ljk5Yy0wLC0zOC42MzUgMTUuNjg2LC03My41ODggNDEuMDY2LC05OC45ODljMjUuNDAxLC0yNS4zOCA2MC4zNTQsLTQxLjA2NiA5OC45ODksLTQxLjA2NmMxLjgwMSwwIDMuNTYsMC4xODkgNS4zNTIsMC4yNjhjLTMuMzQzLDUuODIzIC01LjM0MywxMi41MjcgLTUuMzUyLDE5LjczOGMwLjAxOCwxNC45MzUgOC4zMDQsMjcuNzQyIDIwLjM3OSwzNC41NzVjLTAuMTkyLDEuNzggLTAuMzczLDMuNTYgLTAuMzczLDUuNDRjMC4wMjIsMzMuMTI1IDI2LjkwMyw2MC4wMDcgNjAuMDI1LDYwLjAyNWMxLjg4LDAgMy42NjQsLTAuMTggNS40NDMsLTAuMzY5YzYuODMzLDEyLjA2NSAxOS42MjgsMjAuMzU2IDM0LjU3MiwyMC4zNzhjNy4yMTUsLTAuMDA5IDEzLjkxNiwtMi4wMTEgMTkuNzQxLC01LjM1MmMwLjA4LDEuNzggMC4yNjksMy41NTEgMC4yNjksNS4zNTJjLTAsMzguNjM1IC0xNS42ODYsNzMuNTg5IC00MS4wNjYsOTguOTlabS01OC45NzQsLTE4Ljk1OWMtMCwxMS4wNTIgLTguOTU4LDIwLjAxIC0yMC4wMSwyMC4wMWMtMTEuMDQ4LC0wIC0yMC4wMDUsLTguOTU4IC0yMC4wMDUsLTIwLjAxYy0wLC0xMS4wNDkgOC45NTcsLTIwLjAwNiAyMC4wMDUsLTIwLjAwNmMxMS4wNTIsLTAgMjAuMDEsOC45NTcgMjAuMDEsMjAuMDA2Wm0tODAuMDMxLC0xMC4wMDVjMCw1LjUyNiAtNC40NzksMTAuMDA1IC0xMC4wMDUsMTAuMDA1Yy01LjUyNiwtMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjMgNC40NzksLTEwLjAwMSAxMC4wMDUsLTEwLjAwMWM1LjUyNiwtMCAxMC4wMDUsNC40NzggMTAuMDA1LDEwLjAwMVptMTQwLjA1NSwtMjAuMDA2YzAsNS41MjYgLTQuNDc5LDEwLjAwNSAtMTAuMDA1LDEwLjAwNWMtNS41MjUsMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjYgNC40OCwtMTAuMDA1IDEwLjAwNSwtMTAuMDA1YzUuNTI2LDAgMTAuMDA1LDQuNDc5IDEwLjAwNSwxMC4wMDVabS0xNjAuMDY0LC01MC4wMmMtMCwxMS4wNDggLTguOTU3LDIwLjAwNiAtMjAuMDEsMjAuMDA2Yy0xMS4wNDgsMCAtMjAuMDA1LC04Ljk1OCAtMjAuMDA1LC0yMC4wMDZjLTAsLTExLjA1MiA4Ljk1NywtMjAuMDEgMjAuMDA1LC0yMC4wMWMxMS4wNTMsMCAyMC4wMSw4Ljk1OCAyMC4wMSwyMC4wMVptODAuMDMsMTAuMDA1YzAsNS41MjMgLTQuNDc4LDEwLjAwMSAtMTAuMDAxLDEwLjAwMWMtNS41MjYsMCAtMTAuMDA1LC00LjQ3OCAtMTAuMDA1LC0xMC4wMDFjMCwtNS41MjYgNC40NzksLTEwLjAwNSAxMC4wMDUsLTEwLjAwNWM1LjUyMywwIDEwLjAwMSw0LjQ3OSAxMC4wMDEsMTAuMDA1Wm0xMTUuNDkzLC02OS40MDZjMCw1LjUyNiAtNC40NzksMTAuMDA1IC0xMC4wMDUsMTAuMDA1Yy01LjUyNiwtMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjYgNC40NzksLTEwLjAwNSAxMC4wMDUsLTEwLjAwNWM1LjUyNiwtMCAxMC4wMDUsNC40NzkgMTAuMDA1LDEwLjAwNVptLTM1LjUyMywtMTkuODc0Yy0wLDExLjUwMyAtOS4zMjUsMjAuODI4IC0yMC44MjgsMjAuODI4Yy0xMS41MDQsLTAgLTIwLjgyOSwtOS4zMjUgLTIwLjgyOSwtMjAuODI4Yy0wLC0xMS41MDMgOS4zMjUsLTIwLjgyOCAyMC44MjksLTIwLjgyOGMxMS41MDMsLTAgMjAuODI4LDkuMzI1IDIwLjgyOCwyMC44MjhabS0xMTkuOTg1LC0wLjc1OWMtMCwxMS4wNTIgLTguOTU3LDIwLjAxIC0yMC4wMDYsMjAuMDFjLTExLjA1MiwtMCAtMjAuMDA5LC04Ljk1OCAtMjAuMDA5LC0yMC4wMWMtMCwtMTEuMDQ4IDguOTU3LC0yMC4wMDYgMjAuMDA5LC0yMC4wMDZjMTEuMDQ5LC0wIDIwLjAwNiw4Ljk1OCAyMC4wMDYsMjAuMDA2WiIgc3R5bGU9ImZpbGw6I2ZmZjtmaWxsLXJ1bGU6bm9uemVybzsiLz48L3N2Zz4=);
1009
- background-position: center center;
1010
- background-repeat: no-repeat;
1011
- background-size: 18px auto;
1012
- }
1013
- </style>
1014
- ';
1015
- }
1016
-
1017
- /**
1018
- * Register WPML (>= 3.2) strings if needed.
1019
- *
1020
- * @return void
1021
- */
1022
- private function register_wpml_strings() {
1023
- // get main instance
1024
- $cn = Cookie_Notice();
1025
-
1026
- global $wpdb;
1027
-
1028
- // prepare strings
1029
- $strings = array(
1030
- 'Message in the notice' => $cn->options['general']['message_text'],
1031
- 'Button text' => $cn->options['general']['accept_text'],
1032
- 'Refuse button text' => $cn->options['general']['refuse_text'],
1033
- 'Revoke message text' => $cn->options['general']['revoke_message_text'],
1034
- 'Revoke button text' => $cn->options['general']['revoke_text'],
1035
- 'Privacy policy text' => $cn->options['general']['see_more_opt']['text'],
1036
- 'Custom link' => $cn->options['general']['see_more_opt']['link']
1037
- );
1038
-
1039
- // get query results
1040
- $results = $wpdb->get_col( $wpdb->prepare( "SELECT name FROM " . $wpdb->prefix . "icl_strings WHERE context = %s", 'Cookie Notice' ) );
1041
-
1042
- // check results
1043
- foreach( $strings as $string => $value ) {
1044
- // string does not exist?
1045
- if ( ! in_array( $string, $results, true ) ) {
1046
- // register string
1047
- do_action( 'wpml_register_single_string', 'Cookie Notice', $string, $value );
1048
- }
1049
- }
1050
- }
1051
-
1052
- /**
1053
- * Display errors and notices.
1054
- *
1055
- * @global string $pagenow
1056
- */
1057
- public function settings_errors() {
1058
- global $pagenow;
1059
-
1060
- // force display notices in top menu settings page
1061
- if ( $pagenow == 'options-general.php' )
1062
- return;
1063
-
1064
- settings_errors( 'cn_cookie_notice_options' );
1065
- }
1066
-
1067
- /**
1068
- * Save compliance config caching.
1069
- */
1070
- public function ajax_purge_cache() {
1071
- if ( ! check_ajax_referer( 'cn-purge-cache', 'nonce' ) )
1072
- echo false;
1073
-
1074
- if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1075
- echo false;
1076
-
1077
- delete_transient( 'cookie_notice_compliance_cache' );
1078
-
1079
- echo true;
1080
- exit;
1081
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1082
  }
1
+ <?php
2
+ // exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) )
4
+ exit;
5
+
6
+ /**
7
+ * Cookie_Notice_Settings class.
8
+ *
9
+ * @class Cookie_Notice_Settings
10
+ */
11
+ class Cookie_Notice_Settings {
12
+
13
+ public $positions = [];
14
+ public $styles = [];
15
+ public $links = [];
16
+ public $link_targets = [];
17
+ public $link_positions = [];
18
+ public $colors = [];
19
+ public $effects = [];
20
+ public $times = [];
21
+ public $script_placements = [];
22
+ public $countries = [];
23
+ public $level_names = [];
24
+ public $text_strings = [];
25
+
26
+ /**
27
+ * Class constructor.
28
+ *
29
+ * @return void
30
+ */
31
+ public function __construct() {
32
+ // actions
33
+ add_action( 'admin_menu', [ $this, 'admin_menu_options' ] );
34
+ add_action( 'network_admin_menu', [ $this, 'admin_menu_options' ] );
35
+ add_action( 'after_setup_theme', [ $this, 'load_defaults' ] );
36
+ add_action( 'admin_init', [ $this, 'validate_network_options' ], 9 );
37
+ add_action( 'admin_init', [ $this, 'register_settings' ] );
38
+ add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
39
+ add_action( 'admin_print_styles', [ $this, 'admin_print_styles' ] );
40
+ add_action( 'wp_ajax_cn_purge_cache', [ $this, 'ajax_purge_cache' ] );
41
+ add_action( 'admin_notices', [ $this, 'settings_errors' ] );
42
+ add_action( 'network_admin_notices', [ $this, 'settings_errors' ] );
43
+ }
44
+
45
+ /**
46
+ * Load plugin defaults.
47
+ *
48
+ * @return void
49
+ */
50
+ public function load_defaults() {
51
+ $this->positions = [
52
+ 'top' => __( 'Top', 'cookie-notice' ),
53
+ 'bottom' => __( 'Bottom', 'cookie-notice' )
54
+ ];
55
+
56
+ $this->styles = [
57
+ 'none' => __( 'None', 'cookie-notice' ),
58
+ 'wp-default' => __( 'Light', 'cookie-notice' ),
59
+ 'bootstrap' => __( 'Dark', 'cookie-notice' )
60
+ ];
61
+
62
+ $this->revoke_opts = [
63
+ 'automatic' => __( 'Automatic', 'cookie-notice' ),
64
+ 'manual' => __( 'Manual', 'cookie-notice' )
65
+ ];
66
+
67
+ $this->links = [
68
+ 'page' => __( 'Page link', 'cookie-notice' ),
69
+ 'custom' => __( 'Custom link', 'cookie-notice' )
70
+ ];
71
+
72
+ $this->link_targets = [ '_blank', '_self' ];
73
+
74
+ $this->link_positions = [
75
+ 'banner' => __( 'Banner', 'cookie-notice' ),
76
+ 'message' => __( 'Message', 'cookie-notice' )
77
+ ];
78
+
79
+ $this->colors = [
80
+ 'text' => __( 'Text color', 'cookie-notice' ),
81
+ 'button' => __( 'Button color', 'cookie-notice' ),
82
+ 'bar' => __( 'Bar color', 'cookie-notice' )
83
+ ];
84
+
85
+ $this->times = apply_filters(
86
+ 'cn_cookie_expiry',
87
+ [
88
+ 'hour' => [ __( 'An hour', 'cookie-notice' ), 3600 ],
89
+ 'day' => [ __( '1 day', 'cookie-notice' ), 86400 ],
90
+ 'week' => [ __( '1 week', 'cookie-notice' ), 604800 ],
91
+ 'month' => [ __( '1 month', 'cookie-notice' ), 2592000 ],
92
+ '3months' => [ __( '3 months', 'cookie-notice' ), 7862400 ],
93
+ '6months' => [ __( '6 months', 'cookie-notice' ), 15811200 ],
94
+ 'year' => [ __( '1 year', 'cookie-notice' ), 31536000 ],
95
+ 'infinity' => [ __( 'infinity', 'cookie-notice' ), 2147483647 ]
96
+ ]
97
+ );
98
+
99
+ $this->effects = [
100
+ 'none' => __( 'None', 'cookie-notice' ),
101
+ 'fade' => __( 'Fade', 'cookie-notice' ),
102
+ 'slide' => __( 'Slide', 'cookie-notice' )
103
+ ];
104
+
105
+ $this->script_placements = [
106
+ 'header' => __( 'Header', 'cookie-notice' ),
107
+ 'footer' => __( 'Footer', 'cookie-notice' )
108
+ ];
109
+
110
+ $this->level_names = [
111
+ 1 => [
112
+ 1 => __( 'Silver', 'cookie-notice' ),
113
+ 2 => __( 'Gold', 'cookie-notice' ),
114
+ 3 => __( 'Platinum', 'cookie-notice' )
115
+ ],
116
+ 2 => [
117
+ 1 => __( 'Private', 'cookie-notice' ),
118
+ 2 => __( 'Balanced', 'cookie-notice' ),
119
+ 3 => __( 'Personalized', 'cookie-notice' )
120
+ ],
121
+ 3 => [
122
+ 1 => __( 'Reject All', 'cookie-notice' ),
123
+ 2 => __( 'Accept Some', 'cookie-notice' ),
124
+ 3 => __( 'Accept All', 'cookie-notice' )
125
+ ]
126
+ ];
127
+
128
+ $this->text_strings = [
129
+ 'saveBtnText' => __( 'Save my preferences', 'cookie-notice' ),
130
+ // 'acceptBtnText' => __( 'Accept', 'cookie-notice' ),
131
+ // 'rejectBtnText' => __( 'Reject', 'cookie-notice' ),
132
+ // 'revokeBtnText' => __( 'Revoke Cookies', 'cookie-notice' ),
133
+ 'privacyBtnText' => __( 'Privacy policy', 'cookie-notice' ),
134
+ 'dontSellBtnText' => __( 'Do Not Sell', 'cookie-notice' ),
135
+ 'customizeBtnText' => __( 'Preferences', 'cookie-notice' ),
136
+ 'headingText' => __( "We believe your data is your property and support your right to privacy and transparency.", 'cookie-notice' ),
137
+ 'bodyText' => __( "Select a Data Access Level and Duration to choose how we use and share your data.", 'cookie-notice' ),
138
+ 'levelBodyText_1' => __( 'Highest level of privacy. Data accessed for necessary site operations only. Data shared with 3rd parties to ensure the site is secure and works on your device.', 'cookie-notice' ),
139
+ 'levelBodyText_2' => __( 'Balanced experience. Data accessed for content personalisation and site optimisation. Data shared with 3rd parties may be used to track and store your preferences for this site.', 'cookie-notice' ),
140
+ 'levelBodyText_3' => __( 'Highest level of personalisation. Data accessed to make ads and media more relevant. Data shared with 3rd parties may be use to track you on this site and other sites you visit.', 'cookie-notice' ),
141
+ 'levelNameText_1' => $this->level_names[1][1],
142
+ 'levelNameText_2' => $this->level_names[1][2],
143
+ 'levelNameText_3' => $this->level_names[1][3],
144
+ 'monthText' => __( 'month', 'cookie-notice' ),
145
+ 'monthsText' => __( 'months', 'cookie-notice' )
146
+ ];
147
+
148
+ // get main instance
149
+ $cn = Cookie_Notice();
150
+
151
+ // set default text strings
152
+ $cn->defaults['general']['message_text'] = __( 'We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.', 'cookie-notice' );
153
+ $cn->defaults['general']['accept_text'] = __( 'Ok', 'cookie-notice' );
154
+ $cn->defaults['general']['refuse_text'] = __( 'No', 'cookie-notice' );
155
+ $cn->defaults['general']['revoke_message_text'] = __( 'You can revoke your consent any time using the Revoke consent button.', 'cookie-notice' );
156
+ $cn->defaults['general']['revoke_text'] = __( 'Revoke consent', 'cookie-notice' );
157
+ $cn->defaults['general']['see_more_opt']['text'] = __( 'Privacy policy', 'cookie-notice' );
158
+
159
+ // set translation strings on plugin activation
160
+ if ( $cn->options['general']['translate'] === true ) {
161
+ $cn->options['general']['translate'] = false;
162
+
163
+ $cn->options['general']['message_text'] = $cn->defaults['general']['message_text'];
164
+ $cn->options['general']['accept_text'] = $cn->defaults['general']['accept_text'];
165
+ $cn->options['general']['refuse_text'] = $cn->defaults['general']['refuse_text'];
166
+ $cn->options['general']['revoke_message_text'] = $cn->defaults['general']['revoke_message_text'];
167
+ $cn->options['general']['revoke_text'] = $cn->defaults['general']['revoke_text'];
168
+ $cn->options['general']['see_more_opt']['text'] = $cn->defaults['general']['see_more_opt']['text'];
169
+
170
+ if ( $cn->is_network_admin() )
171
+ update_site_option( 'cookie_notice_options', $cn->options['general'] );
172
+ else
173
+ update_option( 'cookie_notice_options', $cn->options['general'] );
174
+ }
175
+
176
+ // WPML >= 3.2
177
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
178
+ $this->register_wpml_strings();
179
+ // WPML and Polylang compatibility
180
+ } elseif ( function_exists( 'icl_register_string' ) ) {
181
+ icl_register_string( 'Cookie Notice', 'Message in the notice', $cn->options['general']['message_text'] );
182
+ icl_register_string( 'Cookie Notice', 'Button text', $cn->options['general']['accept_text'] );
183
+ icl_register_string( 'Cookie Notice', 'Refuse button text', $cn->options['general']['refuse_text'] );
184
+ icl_register_string( 'Cookie Notice', 'Revoke message text', $cn->options['general']['revoke_message_text'] );
185
+ icl_register_string( 'Cookie Notice', 'Revoke button text', $cn->options['general']['revoke_text'] );
186
+ icl_register_string( 'Cookie Notice', 'Privacy policy text', $cn->options['general']['see_more_opt']['text'] );
187
+ icl_register_string( 'Cookie Notice', 'Custom link', $cn->options['general']['see_more_opt']['link'] );
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Add submenu.
193
+ *
194
+ * @return void
195
+ */
196
+ public function admin_menu_options() {
197
+ if ( current_action() === 'network_admin_menu' && ! Cookie_Notice()->is_plugin_network_active() )
198
+ return;
199
+
200
+ add_menu_page( __( 'Cookie Notice', 'cookie-notice' ), __( 'Cookies', 'cookie-notice' ), apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ), 'cookie-notice', [ $this, 'options_page' ], 'none', '99.3' );
201
+ }
202
+
203
+ /**
204
+ * Options page output.
205
+ *
206
+ * @return void
207
+ */
208
+ public function options_page() {
209
+ // get main instance
210
+ $cn = Cookie_Notice();
211
+
212
+ // get cookie compliance status
213
+ $status = $cn->get_status();
214
+
215
+ echo '
216
+ <div class="wrap">
217
+ <h2>' . __( 'Cookie Notice & Compliance for GDPR/CCPA', 'cookie-notice' ) . '</h2>
218
+ <div class="cookie-notice-settings">
219
+ <div class="cookie-notice-sidebar">
220
+ <div class="cookie-notice-credits">
221
+ <div class="inside">
222
+ <div class="inner">';
223
+
224
+ // compliance enabled
225
+ if ( $status === 'active' ) {
226
+ echo ' <h2>We\'re Promoting Privacy&trade;</h2>
227
+ <p>' . __( 'Promote the privacy of your website visitors without affecting how you do your business.', 'cookie-notice' ) . '</p>';
228
+ } else {
229
+ echo ' <h1><b>Cookie Compliance&trade;</b></h1>
230
+ <h2>' . __( 'The next generation of Cookie Notice', 'cookie-notice' ) . '</h2>
231
+ <div class="cn-lead">
232
+ <p>' . __( 'A free web application to help you deliver better consent experiences and comply with GDPR, CCPA and other data privacy laws more effectively.', 'cookie-notice' ) . '</p>
233
+ </div>
234
+ <img src="//cns2-53eb.kxcdn.com/screen-dashboard-small.png">
235
+ <a href="https://cookie-compliance.co/" class="button button-primary button-hero cn-button" target="_blank">' . __( 'Learn more', 'cookie-notice' ) . '</a>';
236
+ }
237
+
238
+ echo '
239
+ </div>
240
+ </div>
241
+ </div>';
242
+
243
+ if ( $status !== 'active' ) {
244
+ echo '
245
+ <div class="cookie-notice-faq">
246
+ <h2>' . __( 'F.A.Q.', 'cookie-notice' ) . '</h2>
247
+ <div class="cn-toggle-container">
248
+ <label for="cn-faq-1" class="cn-toggle-item">
249
+ <input id="cn-faq-1" type="checkbox" checked />
250
+ <span class="cn-toggle-heading">' . __( 'Does the Cookie Notice make my site fully compliant with GDPR?', 'cookie-notice' ) . '</span>
251
+ <span class="cn-toggle-body">' . __( 'It is not possible to provide the required technical compliance features using only a WordPress plugin. Features like consent record storage, purpose categories and script blocking that bring your site into full compliance with GDPR are only available through the Cookie Compliance integration.', 'cookie-notice' ) . '
252
+ </label>
253
+ <label for="cn-faq-2" class="cn-toggle-item">
254
+ <input id="cn-faq-2" type="checkbox" />
255
+ <span class="cn-toggle-heading">' . __( 'Does the Cookie Compiance integration make my site fully compliant with GDPR?', 'cookie-notice' ) . '</span>
256
+ <span class="cn-toggle-body">' . __( 'Yes! The plugin + web application version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions.', 'cookie-notice' ) . '</span>
257
+ </label>
258
+ <label for="cn-faq-3" class="cn-toggle-item">
259
+ <input id="cn-faq-3" type="checkbox" />
260
+ <span class="cn-toggle-heading">' . __( 'Is Cookie Compliance free?', 'cookie-notice' ) . '</span>
261
+ <span class="cn-toggle-body">' . __( 'Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website monthly traffic.', 'cookie-notice' ) . '</span>
262
+ </label>
263
+ <label for="cn-faq-4" class="cn-toggle-item">
264
+ <input id="cn-faq-4" type="checkbox" />
265
+ <span class="cn-toggle-heading">' . __( 'Where can I find pricing options?', 'cookie-notice' ) . '</span>
266
+ <span class="cn-toggle-body">' . __( 'You can learn more about the features and pricing by visiting the Cookie Compliance website here:', 'cookie-notice' ) . ' <a href="https://cookie-compliance.co/" target="_blank">https://cookie-compliance.co/</a></span>
267
+ </label>
268
+ </div>
269
+ </div>';
270
+ }
271
+
272
+ echo '
273
+ </div>';
274
+
275
+ // multisite?
276
+ if ( is_multisite() ) {
277
+ // network admin?
278
+ if ( $cn->is_network_admin() ) {
279
+ $form_class = ( $cn->is_plugin_network_active() && ! $cn->options['general']['global_override'] ? ' class="cn-options-disabled"' : '' );
280
+ $form_page = 'admin.php?page=cookie-notice';
281
+ $hidden_input = '<input type="hidden" name="cn-network-settings" value="true" />';
282
+ // single network site
283
+ } else {
284
+ $form_class = ( $cn->is_plugin_network_active() && $cn->network_options['global_override'] ? ' class="cn-options-disabled cn-options-submit-disabled"' : '' );
285
+ $form_page = 'options.php';
286
+ $hidden_input = '';
287
+ }
288
+ // single site
289
+ } else {
290
+ $form_class = '';
291
+ $form_page = 'options.php';
292
+ $hidden_input = '';
293
+ }
294
+
295
+ echo '
296
+ <form action="' . $form_page . '" method="post"' . $form_class . '>';
297
+
298
+ settings_fields( 'cookie_notice_options' );
299
+
300
+ echo $hidden_input;
301
+ echo '
302
+ <div class="cn-options">';
303
+
304
+ do_settings_sections( 'cookie_notice_options' );
305
+
306
+ echo ' </div>
307
+ <p class="submit">';
308
+ submit_button( '', 'primary', 'save_cookie_notice_options', false );
309
+
310
+ echo ' ';
311
+
312
+ submit_button( __( 'Reset to defaults', 'cookie-notice' ), 'secondary', 'reset_cookie_notice_options', false );
313
+ echo '
314
+ </p>
315
+ </form>
316
+ </div>
317
+ <div class="clear"></div>
318
+ </div>';
319
+ }
320
+
321
+ /**
322
+ * Regiseter plugin settings.
323
+ *
324
+ * @return void
325
+ */
326
+ public function register_settings() {
327
+ register_setting( 'cookie_notice_options', 'cookie_notice_options', [ $this, 'validate_options' ] );
328
+
329
+ // get main instance
330
+ $cn = Cookie_Notice();
331
+
332
+ $status = $cn->get_status();
333
+
334
+ // multisite?
335
+ if ( is_multisite() ) {
336
+ // network admin?
337
+ if ( $cn->is_network_admin() ) {
338
+ // network section
339
+ add_settings_section( 'cookie_notice_network', __( 'Network Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
340
+ add_settings_field( 'cn_global_override', __( 'Global Settings Override', 'cookie-notice' ), [ $this, 'cn_global_override' ], 'cookie_notice_options', 'cookie_notice_network' );
341
+ add_settings_field( 'cn_global_cookie', __( 'Global Cookie', 'cookie-notice' ), [ $this, 'cn_global_cookie' ], 'cookie_notice_options', 'cookie_notice_network' );
342
+ } elseif ( $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
343
+ // network section
344
+ add_settings_section( 'cookie_notice_network', __( 'Network Settings', 'cookie-notice' ), [ $this, 'cn_network_section' ], 'cookie_notice_options' );
345
+ add_settings_field( 'cn_dummy', '', '__return_empty_string', 'cookie_notice_options', 'cookie_notice_network' );
346
+
347
+ // get real status of current site
348
+ $status = get_option( 'cookie_notice_status', '' );
349
+
350
+ // get valid status
351
+ $status = $cn->check_status( $status );
352
+ }
353
+ }
354
+
355
+ // compliance enabled
356
+ if ( $status === 'active' ) {
357
+ // compliance section
358
+ add_settings_section( 'cookie_notice_compliance', __( 'Compliance Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
359
+ add_settings_field( 'cn_app_status', __( 'Compliance status', 'cookie-notice' ), [ $this, 'cn_app_status' ], 'cookie_notice_options', 'cookie_notice_compliance' );
360
+ add_settings_field( 'cn_app_id', __( 'App ID', 'cookie-notice' ), [ $this, 'cn_app_id' ], 'cookie_notice_options', 'cookie_notice_compliance' );
361
+ add_settings_field( 'cn_app_key', __( 'App Key', 'cookie-notice' ), [ $this, 'cn_app_key' ], 'cookie_notice_options', 'cookie_notice_compliance' );
362
+
363
+ // configuration section
364
+ add_settings_section( 'cookie_notice_configuration', __( 'Miscellaneous Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
365
+ add_settings_field( 'cn_app_blocking', __( 'Autoblocking', 'cookie-notice' ), [ $this, 'cn_app_blocking' ], 'cookie_notice_options', 'cookie_notice_configuration' );
366
+ add_settings_field( 'cn_hide_banner', __( 'Hide for logged in', 'cookie-notice' ), [ $this, 'cn_hide_banner' ], 'cookie_notice_options', 'cookie_notice_configuration' );
367
+ add_settings_field( 'cn_debug_mode', __( 'Debug mode', 'cookie-notice' ), [ $this, 'cn_debug_mode' ], 'cookie_notice_options', 'cookie_notice_configuration' );
368
+ add_settings_field( 'cn_app_purge_cache', __( 'Cache', 'cookie-notice' ), [ $this, 'cn_app_purge_cache' ], 'cookie_notice_options', 'cookie_notice_configuration' );
369
+ add_settings_field( 'cn_script_placement', __( 'Script placement', 'cookie-notice' ), [ $this, 'cn_script_placement' ], 'cookie_notice_options', 'cookie_notice_configuration' );
370
+ add_settings_field( 'cn_deactivation_delete', __( 'Deactivation', 'cookie-notice' ), [ $this, 'cn_deactivation_delete' ], 'cookie_notice_options', 'cookie_notice_configuration' );
371
+ // compliance disabled
372
+ } else {
373
+ // compliance section
374
+ add_settings_section( 'cookie_notice_compliance', __( 'Compliance Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
375
+ add_settings_field( 'cn_app_status', __( 'Compliance status', 'cookie-notice' ), [ $this, 'cn_app_status' ], 'cookie_notice_options', 'cookie_notice_compliance' );
376
+ add_settings_field( 'cn_app_id', __( 'App ID', 'cookie-notice' ), [ $this, 'cn_app_id' ], 'cookie_notice_options', 'cookie_notice_compliance' );
377
+ add_settings_field( 'cn_app_key', __( 'App Key', 'cookie-notice' ), [ $this, 'cn_app_key' ], 'cookie_notice_options', 'cookie_notice_compliance' );
378
+
379
+ // configuration section
380
+ add_settings_section( 'cookie_notice_configuration', __( 'Notice Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
381
+ add_settings_field( 'cn_message_text', __( 'Message', 'cookie-notice' ), [ $this, 'cn_message_text' ], 'cookie_notice_options', 'cookie_notice_configuration' );
382
+ add_settings_field( 'cn_accept_text', __( 'Button text', 'cookie-notice' ), [ $this, 'cn_accept_text' ], 'cookie_notice_options', 'cookie_notice_configuration' );
383
+ add_settings_field( 'cn_see_more', __( 'Privacy policy', 'cookie-notice' ), [ $this, 'cn_see_more' ], 'cookie_notice_options', 'cookie_notice_configuration' );
384
+ add_settings_field( 'cn_refuse_opt', __( 'Refuse consent', 'cookie-notice' ), [ $this, 'cn_refuse_opt' ], 'cookie_notice_options', 'cookie_notice_configuration' );
385
+ add_settings_field( 'cn_revoke_opt', __( 'Revoke consent', 'cookie-notice' ), [ $this, 'cn_revoke_opt' ], 'cookie_notice_options', 'cookie_notice_configuration' );
386
+ add_settings_field( 'cn_refuse_code', __( 'Script blocking', 'cookie-notice' ), [ $this, 'cn_refuse_code' ], 'cookie_notice_options', 'cookie_notice_configuration' );
387
+ add_settings_field( 'cn_redirection', __( 'Reloading', 'cookie-notice' ), [ $this, 'cn_redirection' ], 'cookie_notice_options', 'cookie_notice_configuration' );
388
+ add_settings_field( 'cn_on_scroll', __( 'On scroll', 'cookie-notice' ), [ $this, 'cn_on_scroll' ], 'cookie_notice_options', 'cookie_notice_configuration' );
389
+ add_settings_field( 'cn_on_click', __( 'On click', 'cookie-notice' ), [ $this, 'cn_on_click' ], 'cookie_notice_options', 'cookie_notice_configuration' );
390
+ add_settings_field( 'cn_time', __( 'Accepted expiry', 'cookie-notice' ), [ $this, 'cn_time' ], 'cookie_notice_options', 'cookie_notice_configuration' );
391
+ add_settings_field( 'cn_time_rejected', __( 'Rejected expiry', 'cookie-notice' ), [ $this, 'cn_time_rejected' ], 'cookie_notice_options', 'cookie_notice_configuration' );
392
+ add_settings_field( 'cn_script_placement', __( 'Script placement', 'cookie-notice' ), [ $this, 'cn_script_placement' ], 'cookie_notice_options', 'cookie_notice_configuration' );
393
+ add_settings_field( 'cn_deactivation_delete', __( 'Deactivation', 'cookie-notice' ), [ $this, 'cn_deactivation_delete' ], 'cookie_notice_options', 'cookie_notice_configuration' );
394
+
395
+ // design section
396
+ add_settings_section( 'cookie_notice_design', __( 'Notice Design', 'cookie-notice' ), '', 'cookie_notice_options' );
397
+ add_settings_field( 'cn_position', __( 'Position', 'cookie-notice' ), [ $this, 'cn_position' ], 'cookie_notice_options', 'cookie_notice_design' );
398
+ add_settings_field( 'cn_hide_effect', __( 'Animation', 'cookie-notice' ), [ $this, 'cn_hide_effect' ], 'cookie_notice_options', 'cookie_notice_design' );
399
+ add_settings_field( 'cn_colors', __( 'Colors', 'cookie-notice' ), [ $this, 'cn_colors' ], 'cookie_notice_options', 'cookie_notice_design' );
400
+ add_settings_field( 'cn_css_class', __( 'Button class', 'cookie-notice' ), [ $this, 'cn_css_class' ], 'cookie_notice_options', 'cookie_notice_design' );
401
+ }
402
+ }
403
+
404
+ /**
405
+ * Network settings override option.
406
+ *
407
+ * @return void
408
+ */
409
+ public function cn_global_override() {
410
+ echo '
411
+ <div id="cn_global_override">
412
+ <label><input type="checkbox" name="cookie_notice_options[global_override]" value="1" ' . checked( true, Cookie_Notice()->options['general']['global_override'], false ) . ' />' . __( 'Enable global network settings override.', 'cookie-notice' ) . '</label>
413
+ <p class="description">' . __( 'Every site in the network will use the same settings. Site administrators will not be able to change them.', 'cookie-notice' ) . '</p>
414
+ </div>';
415
+ }
416
+
417
+ /**
418
+ * Network cookie acceptance option.
419
+ *
420
+ * @return void
421
+ */
422
+ public function cn_global_cookie() {
423
+ $multi_folders = is_multisite() && ! is_subdomain_install();
424
+
425
+ // multisite with path-based network?
426
+ if ( $multi_folders )
427
+ $desc = ' ' . __( 'This option works only for domain-based networks.', 'cookie-notice' );
428
+ else
429
+ $desc = '';
430
+
431
+ echo '
432
+ <div id="cn_global_cookie">
433
+ <label><input type="checkbox" name="cookie_notice_options[global_cookie]" value="1" ' . checked( true, Cookie_Notice()->options['general']['global_cookie'], false ) . ' ' . disabled( $multi_folders, true, false ) . ' />' . __( 'Enable global network cookie consent.', 'cookie-notice' ) . '</label>
434
+ <p class="description">' . __( 'Cookie consent in one of the network sites results in a consent in all of the sites on the network.', 'cookie-notice' ) . $desc . '</p>
435
+ </div>';
436
+ }
437
+
438
+ /**
439
+ * Network settings section.
440
+ *
441
+ * @return void
442
+ */
443
+ public function cn_network_section() {
444
+ echo '
445
+ <p>' . __( 'Global network settings override is active. Every site will use the same network settings. Please contact super administrator if you want to have more control over the settings.', 'cookie-notice' ) . '</p>';
446
+ }
447
+
448
+ /**
449
+ * Compliance status.
450
+ *
451
+ * @return void
452
+ */
453
+ public function cn_app_status() {
454
+ // get main instance
455
+ $cn = Cookie_Notice();
456
+
457
+ // get cookie compliance status
458
+ $app_status = $cn->get_status();
459
+
460
+ switch ( $app_status ) {
461
+ case 'active':
462
+ echo '
463
+ <div id="cn_app_status">
464
+ <span class="cn_compliance_status">' . __( 'Notice', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
465
+ <span class="cn_compliance_status">' . __( 'Autoblocking', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
466
+ <span class="cn_compliance_status">' . __( 'Cookie Categories', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
467
+ <span class="cn_compliance_status">' . __( 'Proof-of-Consent', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
468
+ </div>
469
+ <div id="cn_app_actions">
470
+ <a href="' . esc_url( $cn->get_url( 'login' ) ) . '" class="button button-primary button-hero cn-button" target="_blank">' . __( 'Log in & Configure', 'cookie-notice' ) . '</a>
471
+ <p class="description">' . __( 'Log into the Cookie Compliance&trade; web application and configure your Privacy Experience.', 'cookie-notice' ) . '</p>
472
+ </div>';
473
+ break;
474
+
475
+ case 'pending':
476
+ echo '
477
+ <div id="cn_app_status">
478
+ <span class="cn_compliance_status">' . __( 'Notice', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
479
+ <span class="cn_compliance_status">' . __( 'Autoblocking', 'cookie-notice' ) . ': <label class="cn-pending">' . __( 'Pending', 'cookie-notice' ) . '</label></span>
480
+ <span class="cn_compliance_status">' . __( 'Cookie Categories', 'cookie-notice' ) . ': <label class="cn-pending">' . __( 'Pending', 'cookie-notice' ) . '</label></span>
481
+ <span class="cn_compliance_status">' . __( 'Proof-of-Consent', 'cookie-notice' ) . ': <label class="cn-pending">' . __( 'Pending', 'cookie-notice' ) . '</label></span>
482
+ </div>
483
+ <div id="cn_app_actions">
484
+ <a href="' . esc_url( $cn->get_url( 'login' ) ) . '" class="button button-primary button-hero cn-button" target="_blank">' . __( 'Log in & configure', 'cookie-notice' ) . '</a>
485
+ <p class="description">' . __( 'Log into the Cookie Compliance&trade; web application and complete the setup process.', 'cookie-notice' ) . '</p>
486
+ </div>';
487
+ break;
488
+
489
+ default:
490
+ if ( $cn->is_network_admin() )
491
+ $url = network_admin_url( 'admin.php?page=cookie-notice' );
492
+ else
493
+ $url = admin_url( 'admin.php?page=cookie-notice' );
494
+
495
+ echo '
496
+ <div id="cn_app_status">
497
+ <span class="cn_compliance_status">' . __( 'Notice', 'cookie-notice' ) . ': <label class="cn-active">' . __( 'Active', 'cookie-notice' ) . '</label></span>
498
+ <span class="cn_compliance_status">' . __( 'Autoblocking', 'cookie-notice' ) . ': <label class="cn-inactive">' . __( 'Inactive', 'cookie-notice' ) . '</label></span>
499
+ <span class="cn_compliance_status">' . __( 'Cookie Categories', 'cookie-notice' ) . ': <label class="cn-inactive">' . __( 'Inactive', 'cookie-notice' ) . '</label></span>
500
+ <span class="cn_compliance_status">' . __( 'Proof-of-Consent', 'cookie-notice' ) . ': <label class="cn-inactive">' . __( 'Inactive', 'cookie-notice' ) . '</label></span>
501
+ </div>
502
+ <div id="cn_app_actions">
503
+ <a href="' . esc_url( $url ) . '" class="button button-primary button-hero cn-button cn-run-welcome">' . __( 'Add Compliance features', 'cookie-notice' ) . '</a>
504
+ <p class="description">' . __( 'Sign up to Cookie Compliance&trade; and add GDPR, CCPA and other international data privacy laws compliance features.', 'cookie-notice' ) . '</p>
505
+ </div>';
506
+ break;
507
+ }
508
+ }
509
+
510
+ /**
511
+ * App ID option.
512
+ *
513
+ * @return void
514
+ */
515
+ public function cn_app_id() {
516
+ echo '
517
+ <div id="cn_app_id">
518
+ <input type="text" class="regular-text" name="cookie_notice_options[app_id]" value="' . esc_attr( Cookie_Notice()->options['general']['app_id'] ) . '" />
519
+ <p class="description">' . __( 'Enter your Cookie Compliance&trade; application ID.', 'cookie-notice' ) . '</p>
520
+ </div>';
521
+ }
522
+
523
+ /**
524
+ * App key option.
525
+ *
526
+ * @return void
527
+ */
528
+ public function cn_app_key() {
529
+ echo '
530
+ <div id="cn_app_key">
531
+ <input type="password" class="regular-text" name="cookie_notice_options[app_key]" value="' . esc_attr( Cookie_Notice()->options['general']['app_key'] ) . '" />
532
+ <p class="description">' . __( 'Enter your Cookie Compliance&trade; application secret key.', 'cookie-notice' ) . '</p>
533
+ </div>';
534
+ }
535
+
536
+ /**
537
+ * App autoblocking option.
538
+ *
539
+ * @return void
540
+ */
541
+ public function cn_app_blocking() {
542
+ echo '
543
+ <div id="cn_app_blocking">
544
+ <label><input type="checkbox" name="cookie_notice_options[app_blocking]" value="1" ' . checked( true, Cookie_Notice()->options['general']['app_blocking'], false ) . ' />' . __( 'Enable to automatically block 3rd party scripts before user consent.', 'cookie-notice' ) . '</label>
545
+ <p class="description">' . __( "In case you're experiencing issues with your site disable that feature temporarily.", 'cookie-notice' ) . '</p>
546
+ </div>';
547
+ }
548
+
549
+ /**
550
+ * Purge cache option.
551
+ *
552
+ * @return void
553
+ */
554
+ public function cn_app_purge_cache() {
555
+ echo '
556
+ <div id="cn_app_purge_cache">
557
+ <div class="cn-button-container">
558
+ <a href="#" class="button button-secondary">' . __( 'Purge Cache', 'cookie-notice' ) . '</a>
559
+ </div>
560
+ <p class="description">' . __( 'Click the Purge Cache button to refresh the app configuration.', 'cookie-notice' ) . '</p>
561
+ </div>';
562
+ }
563
+
564
+ /**
565
+ * Hide banner option.
566
+ *
567
+ * @return void
568
+ */
569
+ public function cn_hide_banner() {
570
+ echo '
571
+ <div id="cn_hide_banner">
572
+ <label><input type="checkbox" name="cookie_notice_options[hide_banner]" value="1" ' . checked( true, Cookie_Notice()->options['general']['hide_banner'], false ) . ' />' . __( 'Enable to hide the consent banner for logged in users.', 'cookie-notice' ) . '</label>
573
+ </div>';
574
+ }
575
+
576
+ /**
577
+ * Debug mode option.
578
+ *
579
+ * @return void
580
+ */
581
+ public function cn_debug_mode() {
582
+ echo '
583
+ <div id="cn_debug_mode">
584
+ <label><input type="checkbox" name="cookie_notice_options[debug_mode]" value="1" ' . checked( true, Cookie_Notice()->options['general']['debug_mode'], false ) . ' />' . __( 'Enable to run the consent banner in debug mode.', 'cookie-notice' ) . '</label>
585
+ </div>';
586
+ }
587
+
588
+ /**
589
+ * Cookie notice message option.
590
+ *
591
+ * @return void
592
+ */
593
+ public function cn_message_text() {
594
+ echo '
595
+ <div id="cn_message_text">
596
+ <textarea name="cookie_notice_options[message_text]" class="large-text" cols="50" rows="5">' . esc_textarea( Cookie_Notice()->options['general']['message_text'] ) . '</textarea>
597
+ <p class="description">' . __( 'Enter the cookie notice message.', 'cookie-notice' ) . '</p>
598
+ </div>';
599
+ }
600
+
601
+ /**
602
+ * Accept cookie label option.
603
+ *
604
+ * @return void
605
+ */
606
+ public function cn_accept_text() {
607
+ echo '
608
+ <div id="cn_accept_text">
609
+ <input type="text" class="regular-text" name="cookie_notice_options[accept_text]" value="' . esc_attr( Cookie_Notice()->options['general']['accept_text'] ) . '" />
610
+ <p class="description">' . __( 'The text of the option to accept the notice and make it disappear.', 'cookie-notice' ) . '</p>
611
+ </div>';
612
+ }
613
+
614
+ /**
615
+ * Toggle third party non functional cookies option.
616
+ *
617
+ * @return void
618
+ */
619
+ public function cn_refuse_opt() {
620
+ echo '
621
+ <fieldset>
622
+ <label><input id="cn_refuse_opt" type="checkbox" name="cookie_notice_options[refuse_opt]" value="1" ' . checked( true, Cookie_Notice()->options['general']['refuse_opt'], false ) . ' />' . __( 'Enable to give to the user the possibility to refuse third party non functional cookies.', 'cookie-notice' ) . '</label>
623
+ <div id="cn_refuse_opt_container"' . ( Cookie_Notice()->options['general']['refuse_opt'] === false ? ' style="display: none;"' : '' ) . '>
624
+ <div id="cn_refuse_text">
625
+ <input type="text" class="regular-text" name="cookie_notice_options[refuse_text]" value="' . esc_attr( Cookie_Notice()->options['general']['refuse_text'] ) . '" />
626
+ <p class="description">' . __( 'The text of the button to refuse the consent.', 'cookie-notice' ) . '</p>
627
+ </div>
628
+ </div>
629
+ </fieldset>';
630
+ }
631
+
632
+ /**
633
+ * Non functional cookies code option.
634
+ *
635
+ * @return void
636
+ */
637
+ public function cn_refuse_code() {
638
+ $allowed_html = Cookie_Notice()->get_allowed_html();
639
+ $active = ! empty( Cookie_Notice()->options['general']['refuse_code'] ) && empty( Cookie_Notice()->options['general']['refuse_code_head'] ) ? 'body' : 'head';
640
+
641
+ echo '
642
+ <div id="cn_refuse_code">
643
+ <div id="cn_refuse_code_fields">
644
+ <h2 class="nav-tab-wrapper">
645
+ <a id="refuse_head-tab" class="nav-tab' . ( $active === 'head' ? ' nav-tab-active' : '' ) . '" href="#refuse_head">' . __( 'Head', 'cookie-notice' ) . '</a>
646
+ <a id="refuse_body-tab" class="nav-tab' . ( $active === 'body' ? ' nav-tab-active' : '' ) . '" href="#refuse_body">' . __( 'Body', 'cookie-notice' ) . '</a>
647
+ </h2>
648
+ <div id="refuse_head" class="refuse-code-tab' . ( $active === 'head' ? ' active' : '' ) . '">
649
+ <p class="description">' . __( 'The code to be used in your site header, before the closing head tag.', 'cookie-notice' ) . '</p>
650
+ <textarea name="cookie_notice_options[refuse_code_head]" class="large-text" cols="50" rows="8">' . html_entity_decode( trim( wp_kses( Cookie_Notice()->options['general']['refuse_code_head'], $allowed_html ) ) ) . '</textarea>
651
+ </div>
652
+ <div id="refuse_body" class="refuse-code-tab' . ( $active === 'body' ? ' active' : '' ) . '">
653
+ <p class="description">' . __( 'The code to be used in your site footer, before the closing body tag.', 'cookie-notice' ) . '</p>
654
+ <textarea name="cookie_notice_options[refuse_code]" class="large-text" cols="50" rows="8">' . html_entity_decode( trim( wp_kses( Cookie_Notice()->options['general']['refuse_code'], $allowed_html ) ) ) . '</textarea>
655
+ </div>
656
+ </div>
657
+ <p class="description">' . __( 'Enter non functional cookies Javascript code here (for e.g. Google Analitycs) to be used after the notice is accepted.', 'cookie-notice' ) . '</br>' . __( 'To get the user consent status use the <code>cn_cookies_accepted()</code> function.', 'cookie-notice' ) . '</p>
658
+ </div>';
659
+ }
660
+
661
+ /**
662
+ * Revoke cookies option.
663
+ *
664
+ * @return void
665
+ */
666
+ public function cn_revoke_opt() {
667
+ echo '
668
+ <fieldset>
669
+ <div id="cn_revoke_opt">
670
+ <label><input id="cn_revoke_cookies" type="checkbox" name="cookie_notice_options[revoke_cookies]" value="1" ' . checked( true, Cookie_Notice()->options['general']['revoke_cookies'], false ) . ' />' . __( 'Enable to give to the user the possibility to revoke their consent <i>(requires "Refuse consent" option enabled)</i>.', 'cookie-notice' ) . '</label>
671
+ <div id="cn_revoke_opt_container"' . ( Cookie_Notice()->options['general']['revoke_cookies'] ? '' : ' style="display: none;"' ) . '>
672
+ <textarea name="cookie_notice_options[revoke_message_text]" class="large-text" cols="50" rows="2">' . esc_textarea( Cookie_Notice()->options['general']['revoke_message_text'] ) . '</textarea>
673
+ <p class="description">' . __( 'Enter the revoke message.', 'cookie-notice' ) . '</p>
674
+ <input type="text" class="regular-text" name="cookie_notice_options[revoke_text]" value="' . esc_attr( Cookie_Notice()->options['general']['revoke_text'] ) . '" />
675
+ <p class="description">' . __( 'The text of the button to revoke the consent.', 'cookie-notice' ) . '</p>';
676
+
677
+ foreach ( $this->revoke_opts as $value => $label ) {
678
+ echo '
679
+ <label><input id="cn_revoke_cookies-' . $value . '" type="radio" name="cookie_notice_options[revoke_cookies_opt]" value="' . $value . '" ' . checked( $value, Cookie_Notice()->options['general']['revoke_cookies_opt'], false ) . ' />' . esc_html( $label ) . '</label>';
680
+ }
681
+
682
+ echo '
683
+ <p class="description">' . __( 'Select the method for displaying the revoke button - automatic (in the banner) or manual using <code>[cookies_revoke]</code> shortcode.', 'cookie-notice' ) . '</p>
684
+ </div>
685
+ </div>
686
+ <fieldset>';
687
+ }
688
+
689
+ /**
690
+ * Redirection on cookie accept option.
691
+ *
692
+ * @return void
693
+ */
694
+ public function cn_redirection() {
695
+ echo '
696
+ <div id="cn_redirection">
697
+ <label><input type="checkbox" name="cookie_notice_options[redirection]" value="1" ' . checked( true, Cookie_Notice()->options['general']['redirection'], false ) . ' />' . __( 'Enable to reload the page after the notice is accepted.', 'cookie-notice' ) . '</label>
698
+ </div>';
699
+ }
700
+
701
+ /**
702
+ * Privacy policy link option.
703
+ *
704
+ * @global string $wp_version
705
+ *
706
+ * @return void
707
+ */
708
+ public function cn_see_more() {
709
+ $pages = get_pages(
710
+ [
711
+ 'sort_order' => 'ASC',
712
+ 'sort_column' => 'post_title',
713
+ 'hierarchical' => 0,
714
+ 'child_of' => 0,
715
+ 'parent' => -1,
716
+ 'offset' => 0,
717
+ 'post_type' => 'page',
718
+ 'post_status' => 'publish'
719
+ ]
720
+ );
721
+
722
+ echo '
723
+ <fieldset>
724
+ <label><input id="cn_see_more" type="checkbox" name="cookie_notice_options[see_more]" value="1" ' . checked( true, Cookie_Notice()->options['general']['see_more'], false ) . ' />' . __( 'Enable privacy policy link.', 'cookie-notice' ) . '</label>
725
+ <div id="cn_see_more_opt"' . (Cookie_Notice()->options['general']['see_more'] === false ? ' style="display: none;"' : '') . '>
726
+ <input type="text" class="regular-text" name="cookie_notice_options[see_more_opt][text]" value="' . esc_attr( Cookie_Notice()->options['general']['see_more_opt']['text'] ) . '" />
727
+ <p class="description">' . __( 'The text of the privacy policy button.', 'cookie-notice' ) . '</p>
728
+ <div id="cn_see_more_opt_custom_link">';
729
+
730
+ foreach ( $this->links as $value => $label ) {
731
+ $value = esc_attr( $value );
732
+
733
+ echo '
734
+ <label><input id="cn_see_more_link-' . $value . '" type="radio" name="cookie_notice_options[see_more_opt][link_type]" value="' . $value . '" ' . checked( $value, Cookie_Notice()->options['general']['see_more_opt']['link_type'], false ) . ' />' . esc_html( $label ) . '</label>';
735
+ }
736
+
737
+ echo '
738
+ </div>
739
+ <p class="description">' . __( 'Select where to redirect user for more information.', 'cookie-notice' ) . '</p>
740
+ <div id="cn_see_more_opt_page"' . (Cookie_Notice()->options['general']['see_more_opt']['link_type'] === 'custom' ? ' style="display: none;"' : '') . '>
741
+ <select name="cookie_notice_options[see_more_opt][id]">
742
+ <option value="0" ' . selected( 0, Cookie_Notice()->options['general']['see_more_opt']['id'], false ) . '>' . __( '-- select page --', 'cookie-notice' ) . '</option>';
743
+
744
+ if ( $pages ) {
745
+ foreach ( $pages as $page ) {
746
+ echo '
747
+ <option value="' . $page->ID . '" ' . selected( $page->ID, Cookie_Notice()->options['general']['see_more_opt']['id'], false ) . '>' . esc_html( $page->post_title ) . '</option>';
748
+ }
749
+ }
750
+
751
+ echo '
752
+ </select>
753
+ <p class="description">' . __( 'Select from one of your site\'s pages.', 'cookie-notice' ) . '</p>';
754
+
755
+ global $wp_version;
756
+
757
+ if ( version_compare( $wp_version, '4.9.6', '>=' ) ) {
758
+ echo '
759
+ <label><input id="cn_see_more_opt_sync" type="checkbox" name="cookie_notice_options[see_more_opt][sync]" value="1" ' . checked( true, Cookie_Notice()->options['general']['see_more_opt']['sync'], false ) . ' />' . __( 'Synchronize with WordPress Privacy Policy page.', 'cookie-notice' ) . '</label>';
760
+ }
761
+
762
+ echo '
763
+ </div>
764
+ <div id="cn_see_more_opt_link"' . (Cookie_Notice()->options['general']['see_more_opt']['link_type'] === 'page' ? ' style="display: none;"' : '') . '>
765
+ <input type="text" class="regular-text" name="cookie_notice_options[see_more_opt][link]" value="' . esc_attr( Cookie_Notice()->options['general']['see_more_opt']['link'] ) . '" />
766
+ <p class="description">' . __( 'Enter the full URL starting with http(s)://', 'cookie-notice' ) . '</p>
767
+ </div>
768
+ <div id="cn_see_more_link_target">';
769
+
770
+ foreach ( $this->link_targets as $target ) {
771
+ echo '
772
+ <label><input id="cn_see_more_link_target-' . $target . '" type="radio" name="cookie_notice_options[link_target]" value="' . $target . '" ' . checked( $target, Cookie_Notice()->options['general']['link_target'], false ) . ' />' . $target . '</label>';
773
+ }
774
+
775
+ echo '
776
+ <p class="description">' . esc_html__( 'Select the privacy policy link target.', 'cookie-notice' ) . '</p>
777
+ </div>
778
+ <div id="cn_see_more_link_position">';
779
+
780
+ foreach ( $this->link_positions as $position => $label ) {
781
+ echo '
782
+ <label><input id="cn_see_more_link_position-' . $position . '" type="radio" name="cookie_notice_options[link_position]" value="' . $position . '" ' . checked( $position, Cookie_Notice()->options['general']['link_position'], false ) . ' />' . esc_html( $label ) . '</label>';
783
+ }
784
+
785
+ echo '
786
+ <p class="description">' . esc_html__( 'Select the privacy policy link position.', 'cookie-notice' ) . '</p>
787
+ </div>
788
+ </div>
789
+ </fieldset>';
790
+ }
791
+
792
+ /**
793
+ * Expiration time option.
794
+ *
795
+ * @return void
796
+ */
797
+ public function cn_time() {
798
+ echo '
799
+ <div id="cn_time">
800
+ <select name="cookie_notice_options[time]">';
801
+
802
+ foreach ( $this->times as $time => $arr ) {
803
+ $time = esc_attr( $time );
804
+
805
+ echo '
806
+ <option value="' . $time . '" ' . selected( $time, Cookie_Notice()->options['general']['time'] ) . '>' . esc_html( $arr[0] ) . '</option>';
807
+ }
808
+
809
+ echo '
810
+ </select>
811
+ <p class="description">' . __( 'The amount of time that the cookie should be stored for when user accepts the notice.', 'cookie-notice' ) . '</p>
812
+ </div>';
813
+ }
814
+
815
+ /**
816
+ * Expiration time option.
817
+ *
818
+ * @return void
819
+ */
820
+ public function cn_time_rejected() {
821
+ echo '
822
+ <div id="cn_time_rejected">
823
+ <select name="cookie_notice_options[time_rejected]">';
824
+
825
+ foreach ( $this->times as $time => $arr ) {
826
+ $time = esc_attr( $time );
827
+
828
+ echo '
829
+ <option value="' . $time . '" ' . selected( $time, Cookie_Notice()->options['general']['time_rejected'] ) . '>' . esc_html( $arr[0] ) . '</option>';
830
+ }
831
+
832
+ echo '
833
+ </select>
834
+ <p class="description">' . __( 'The amount of time that the cookie should be stored for when the user doesn\'t accept the notice.', 'cookie-notice' ) . '</p>
835
+ </div>';
836
+ }
837
+
838
+ /**
839
+ * Script placement option.
840
+ *
841
+ * @return void
842
+ */
843
+ public function cn_script_placement() {
844
+ echo '
845
+ <div id="cn_script_placement">';
846
+
847
+ foreach ( $this->script_placements as $value => $label ) {
848
+ echo '
849
+ <label><input id="cn_script_placement-' . $value . '" type="radio" name="cookie_notice_options[script_placement]" value="' . esc_attr( $value ) . '" ' . checked( $value, Cookie_Notice()->options['general']['script_placement'], false ) . ' />' . esc_html( $label ) . '</label>';
850
+ }
851
+
852
+ echo '
853
+ <p class="description">' . __( 'Select where all the plugin scripts should be placed.', 'cookie-notice' ) . '</p>
854
+ </div>';
855
+ }
856
+
857
+ /**
858
+ * Position option.
859
+ *
860
+ * @return void
861
+ */
862
+ public function cn_position() {
863
+ echo '
864
+ <div id="cn_position">';
865
+
866
+ foreach ( $this->positions as $value => $label ) {
867
+ $value = esc_attr( $value );
868
+
869
+ echo '
870
+ <label><input id="cn_position-' . $value . '" type="radio" name="cookie_notice_options[position]" value="' . $value . '" ' . checked( $value, Cookie_Notice()->options['general']['position'], false ) . ' />' . esc_html( $label ) . '</label>';
871
+ }
872
+
873
+ echo '
874
+ <p class="description">' . __( 'Select location for the notice.', 'cookie-notice' ) . '</p>
875
+ </div>';
876
+ }
877
+
878
+ /**
879
+ * Animation effect option.
880
+ *
881
+ * @return void
882
+ */
883
+ public function cn_hide_effect() {
884
+ echo '
885
+ <div id="cn_hide_effect">';
886
+
887
+ foreach ( $this->effects as $value => $label ) {
888
+ $value = esc_attr( $value );
889
+
890
+ echo '
891
+ <label><input id="cn_hide_effect-' . $value . '" type="radio" name="cookie_notice_options[hide_effect]" value="' . $value . '" ' . checked( $value, Cookie_Notice()->options['general']['hide_effect'], false ) . ' />' . esc_html( $label ) . '</label>';
892
+ }
893
+
894
+ echo '
895
+ <p class="description">' . __( 'Select the animation style.', 'cookie-notice' ) . '</p>
896
+ </div>';
897
+ }
898
+
899
+ /**
900
+ * On scroll option.
901
+ *
902
+ * @return void
903
+ */
904
+ public function cn_on_scroll() {
905
+ echo '
906
+ <fieldset>
907
+ <label><input id="cn_on_scroll" type="checkbox" name="cookie_notice_options[on_scroll]" value="1" ' . checked( true, Cookie_Notice()->options['general']['on_scroll'], false ) . ' />' . __( 'Enable to accept the notice when user scrolls.', 'cookie-notice' ) . '</label>
908
+ <div id="cn_on_scroll_offset"' . ( Cookie_Notice()->options['general']['on_scroll'] === false || Cookie_Notice()->options['general']['on_scroll'] == false ? ' style="display: none;"' : '' ) . '>
909
+ <input type="text" class="text" name="cookie_notice_options[on_scroll_offset]" value="' . esc_attr( Cookie_Notice()->options['general']['on_scroll_offset'] ) . '" /> <span>px</span>
910
+ <p class="description">' . __( 'Number of pixels user has to scroll to accept the notice and make it disappear.', 'cookie-notice' ) . '</p>
911
+ </div>
912
+ </fieldset>';
913
+ }
914
+
915
+ /**
916
+ * On click option.
917
+ *
918
+ * @return void
919
+ */
920
+ public function cn_on_click() {
921
+ echo '
922
+ <div id="cn_on_click">
923
+ <label><input type="checkbox" name="cookie_notice_options[on_click]" value="1" ' . checked( true, Cookie_Notice()->options['general']['on_click'], false ) . ' />' . __( 'Enable to accept the notice on any click on the page.', 'cookie-notice' ) . '</label>
924
+ </div>';
925
+ }
926
+
927
+ /**
928
+ * Delete plugin data on deactivation option.
929
+ *
930
+ * @return void
931
+ */
932
+ public function cn_deactivation_delete() {
933
+ echo '
934
+ <div id="cn_deactivation_delete">
935
+ <label><input type="checkbox" name="cookie_notice_options[deactivation_delete]" value="1" ' . checked( true, Cookie_Notice()->options['general']['deactivation_delete'], false ) . '/>' . __( 'Enable if you want all plugin data to be deleted on deactivation.', 'cookie-notice' ) . '</label>
936
+ </div>';
937
+ }
938
+
939
+ /**
940
+ * CSS style option.
941
+ *
942
+ * @return void
943
+ */
944
+ public function cn_css_class() {
945
+ echo '
946
+ <div id="cn_css_class">
947
+ <input type="text" class="regular-text" name="cookie_notice_options[css_class]" value="' . esc_attr( Cookie_Notice()->options['general']['css_class'] ) . '" />
948
+ <p class="description">' . __( 'Enter additional button CSS classes separated by spaces.', 'cookie-notice' ) . '</p>
949
+ </div>';
950
+ }
951
+
952
+ /**
953
+ * Colors option.
954
+ *
955
+ * @return void
956
+ */
957
+ public function cn_colors() {
958
+ echo '
959
+ <fieldset>
960
+ <div id="cn_colors">';
961
+
962
+ foreach ( $this->colors as $value => $label ) {
963
+ $value = esc_attr( $value );
964
+
965
+ echo '
966
+ <div id="cn_colors-' . $value . '"><label>' . esc_html( $label ) . '</label><br />
967
+ <input class="cn_color" type="text" name="cookie_notice_options[colors][' . $value . ']" value="' . esc_attr( Cookie_Notice()->options['general']['colors'][$value] ) . '" />
968
+ </div>';
969
+ }
970
+
971
+ $opacity = (int) Cookie_Notice()->options['general']['colors']['bar_opacity'];
972
+
973
+ echo '
974
+ <div id="cn_colors-bar_opacity"><label>' . __( 'Bar opacity', 'cookie-notice' ) . '</label><br />
975
+ <div><input id="cn_colors_bar_opacity_range" class="cn_range" type="range" min="50" max="100" step="1" name="cookie_notice_options[colors][bar_opacity]" value="' . $opacity . '" onchange="cn_colors_bar_opacity_text.value = cn_colors_bar_opacity_range.value" /><input id="cn_colors_bar_opacity_text" class="small-text" type="number" onchange="cn_colors_bar_opacity_range.value = cn_colors_bar_opacity_text.value" min="50" max="100" value="' . $opacity . '" /></div>
976
+ </div>';
977
+
978
+ echo '
979
+ </div>
980
+ </fieldset>';
981
+ }
982
+
983
+ /**
984
+ * Validate options.
985
+ *
986
+ * @param array $input
987
+ * @return array
988
+ */
989
+ public function validate_options( $input ) {
990
+ if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
991
+ return $input;
992
+
993
+ // get main instance
994
+ $cn = Cookie_Notice();
995
+
996
+ $is_network = $cn->is_network_admin();
997
+
998
+ if ( isset( $_POST['save_cookie_notice_options'] ) ) {
999
+ // app id
1000
+ $input['app_id'] = sanitize_text_field( isset( $input['app_id'] ) ? $input['app_id'] : $cn->defaults['general']['app_id'] );
1001
+
1002
+ // app key
1003
+ $input['app_key'] = sanitize_text_field( isset( $input['app_key'] ) ? $input['app_key'] : $cn->defaults['general']['app_key'] );
1004
+
1005
+ // set app status
1006
+ if ( ! empty( $input['app_id'] ) && ! empty( $input['app_key'] ) ) {
1007
+ $app_status = esc_attr( $cn->welcome_api->get_app_status( $input['app_id'] ) );
1008
+
1009
+ if ( $cn->check_status( $app_status ) === 'active' && $cn->options['general']['app_id'] !== $input['app_id'] && $cn->options['general']['app_key'] !== $input['app_key'] ) {
1010
+ // update analytics data
1011
+ $cn->welcome_api->get_app_analytics( true );
1012
+ }
1013
+
1014
+ if ( $is_network )
1015
+ update_site_option( 'cookie_notice_status', $app_status );
1016
+ else
1017
+ update_option( 'cookie_notice_status', $app_status );
1018
+ } else {
1019
+ if ( $is_network )
1020
+ update_site_option( 'cookie_notice_status', '' );
1021
+ else
1022
+ update_option( 'cookie_notice_status', '' );
1023
+ }
1024
+
1025
+ // app blocking
1026
+ $input['app_blocking'] = isset( $input['app_blocking'] );
1027
+
1028
+ // hide banner
1029
+ $input['hide_banner'] = isset( $input['hide_banner'] );
1030
+
1031
+ // debug mode
1032
+ $input['debug_mode'] = isset( $input['debug_mode'] );
1033
+
1034
+ // position
1035
+ $input['position'] = sanitize_text_field( isset( $input['position'] ) && in_array( $input['position'], array_keys( $this->positions ) ) ? $input['position'] : $cn->defaults['general']['position'] );
1036
+
1037
+ // colors
1038
+ $input['colors']['text'] = sanitize_text_field( isset( $input['colors']['text'] ) && $input['colors']['text'] !== '' && preg_match( '/^#[a-f0-9]{6}$/', $input['colors']['text'] ) === 1 ? $input['colors']['text'] : $cn->defaults['general']['colors']['text'] );
1039
+ $input['colors']['button'] = sanitize_text_field( isset( $input['colors']['button'] ) && $input['colors']['button'] !== '' && preg_match( '/^#[a-f0-9]{6}$/', $input['colors']['button'] ) === 1 ? $input['colors']['button'] : $cn->defaults['general']['colors']['button'] );
1040
+ $input['colors']['bar'] = sanitize_text_field( isset( $input['colors']['bar'] ) && $input['colors']['bar'] !== '' && preg_match( '/^#[a-f0-9]{6}$/', $input['colors']['bar'] ) === 1 ? $input['colors']['bar'] : $cn->defaults['general']['colors']['bar'] );
1041
+ $input['colors']['bar_opacity'] = absint( isset( $input['colors']['bar_opacity'] ) && $input['colors']['bar_opacity'] >= 50 ? $input['colors']['bar_opacity'] : $cn->defaults['general']['colors']['bar_opacity'] );
1042
+
1043
+ // texts
1044
+ $input['message_text'] = wp_kses_post( isset( $input['message_text'] ) && $input['message_text'] !== '' ? $input['message_text'] : $cn->defaults['general']['message_text'] );
1045
+ $input['accept_text'] = sanitize_text_field( isset( $input['accept_text'] ) && $input['accept_text'] !== '' ? $input['accept_text'] : $cn->defaults['general']['accept_text'] );
1046
+ $input['refuse_text'] = sanitize_text_field( isset( $input['refuse_text'] ) && $input['refuse_text'] !== '' ? $input['refuse_text'] : $cn->defaults['general']['refuse_text'] );
1047
+ $input['revoke_message_text'] = wp_kses_post( isset( $input['revoke_message_text'] ) && $input['revoke_message_text'] !== '' ? $input['revoke_message_text'] : $cn->defaults['general']['revoke_message_text'] );
1048
+ $input['revoke_text'] = sanitize_text_field( isset( $input['revoke_text'] ) && $input['revoke_text'] !== '' ? $input['revoke_text'] : $cn->defaults['general']['revoke_text'] );
1049
+ $input['refuse_opt'] = isset( $input['refuse_opt'] );
1050
+ $input['revoke_cookies'] = isset( $input['revoke_cookies'] );
1051
+ $input['revoke_cookies_opt'] = isset( $input['revoke_cookies_opt'] ) && array_key_exists( $input['revoke_cookies_opt'], $this->revoke_opts ) ? $input['revoke_cookies_opt'] : $cn->defaults['general']['revoke_cookies_opt'];
1052
+
1053
+ // get allowed HTML
1054
+ $allowed_html = $cn->get_allowed_html();
1055
+
1056
+ // body refuse code
1057
+ $input['refuse_code'] = wp_kses( isset( $input['refuse_code'] ) && $input['refuse_code'] !== '' ? $input['refuse_code'] : $cn->defaults['general']['refuse_code'], $allowed_html );
1058
+
1059
+ // head refuse code
1060
+ $input['refuse_code_head'] = wp_kses( isset( $input['refuse_code_head'] ) && $input['refuse_code_head'] !== '' ? $input['refuse_code_head'] : $cn->defaults['general']['refuse_code_head'], $allowed_html );
1061
+
1062
+ // css button class
1063
+ $input['css_class'] = sanitize_text_field( isset( $input['css_class'] ) ? $input['css_class'] : $cn->defaults['general']['css_class'] );
1064
+
1065
+ // link target
1066
+ $input['link_target'] = sanitize_text_field( isset( $input['link_target'] ) && in_array( $input['link_target'], array_keys( $this->link_targets ) ) ? $input['link_target'] : $cn->defaults['general']['link_target'] );
1067
+
1068
+ // time
1069
+ $input['time'] = sanitize_text_field( isset( $input['time'] ) && in_array( $input['time'], array_keys( $this->times ) ) ? $input['time'] : $cn->defaults['general']['time'] );
1070
+ $input['time_rejected'] = sanitize_text_field( isset( $input['time_rejected'] ) && in_array( $input['time_rejected'], array_keys( $this->times ) ) ? $input['time_rejected'] : $cn->defaults['general']['time_rejected'] );
1071
+
1072
+ // script placement
1073
+ $input['script_placement'] = sanitize_text_field( isset( $input['script_placement'] ) && in_array( $input['script_placement'], array_keys( $this->script_placements ) ) ? $input['script_placement'] : $cn->defaults['general']['script_placement'] );
1074
+
1075
+ // hide effect
1076
+ $input['hide_effect'] = sanitize_text_field( isset( $input['hide_effect'] ) && in_array( $input['hide_effect'], array_keys( $this->effects ) ) ? $input['hide_effect'] : $cn->defaults['general']['hide_effect'] );
1077
+
1078
+ // redirection
1079
+ $input['redirection'] = isset( $input['redirection'] );
1080
+
1081
+ // on scroll
1082
+ $input['on_scroll'] = isset( $input['on_scroll'] );
1083
+
1084
+ // on scroll offset
1085
+ $input['on_scroll_offset'] = absint( isset( $input['on_scroll_offset'] ) && $input['on_scroll_offset'] !== '' ? $input['on_scroll_offset'] : $cn->defaults['general']['on_scroll_offset'] );
1086
+
1087
+ // on click
1088
+ $input['on_click'] = isset( $input['on_click'] );
1089
+
1090
+ // deactivation
1091
+ $input['deactivation_delete'] = isset( $input['deactivation_delete'] );
1092
+
1093
+ // privacy policy
1094
+ $input['see_more'] = isset( $input['see_more'] );
1095
+ $input['see_more_opt']['text'] = sanitize_text_field( isset( $input['see_more_opt']['text'] ) && $input['see_more_opt']['text'] !== '' ? $input['see_more_opt']['text'] : $cn->defaults['general']['see_more_opt']['text'] );
1096
+ $input['see_more_opt']['link_type'] = sanitize_text_field( isset( $input['see_more_opt']['link_type'] ) && in_array( $input['see_more_opt']['link_type'], array_keys( $this->links ) ) ? $input['see_more_opt']['link_type'] : $cn->defaults['general']['see_more_opt']['link_type'] );
1097
+
1098
+ if ( $input['see_more_opt']['link_type'] === 'custom' )
1099
+ $input['see_more_opt']['link'] = ( $input['see_more'] === true ? esc_url( $input['see_more_opt']['link'] ) : '' );
1100
+ elseif ( $input['see_more_opt']['link_type'] === 'page' ) {
1101
+ $input['see_more_opt']['id'] = ( $input['see_more'] === true ? (int) $input['see_more_opt']['id'] : 0 );
1102
+ $input['see_more_opt']['sync'] = isset( $input['see_more_opt']['sync'] );
1103
+
1104
+ if ( $input['see_more_opt']['sync'] )
1105
+ update_option( 'wp_page_for_privacy_policy', $input['see_more_opt']['id'] );
1106
+ }
1107
+
1108
+ // policy link position
1109
+ $input['link_position'] = sanitize_text_field( isset( $input['link_position'] ) && in_array( $input['link_position'], array_keys( $this->link_positions ) ) ? $input['link_position'] : $cn->defaults['general']['link_position'] );
1110
+
1111
+ // message link position?
1112
+ if ( $input['see_more'] === true && $input['link_position'] === 'message' && strpos( $input['message_text'], '[cookies_policy_link' ) === false )
1113
+ $input['message_text'] .= ' [cookies_policy_link]';
1114
+
1115
+ $input['update_version'] = $cn->options['general']['update_version'];
1116
+ $input['update_notice'] = $cn->options['general']['update_notice'];
1117
+
1118
+ $input['translate'] = false;
1119
+
1120
+ // WPML >= 3.2
1121
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
1122
+ do_action( 'wpml_register_single_string', 'Cookie Notice', 'Message in the notice', $input['message_text'] );
1123
+ do_action( 'wpml_register_single_string', 'Cookie Notice', 'Button text', $input['accept_text'] );
1124
+ do_action( 'wpml_register_single_string', 'Cookie Notice', 'Refuse button text', $input['refuse_text'] );
1125
+ do_action( 'wpml_register_single_string', 'Cookie Notice', 'Revoke message text', $input['revoke_message_text'] );
1126
+ do_action( 'wpml_register_single_string', 'Cookie Notice', 'Revoke button text', $input['revoke_text'] );
1127
+ do_action( 'wpml_register_single_string', 'Cookie Notice', 'Privacy policy text', $input['see_more_opt']['text'] );
1128
+
1129
+ if ( $input['see_more_opt']['link_type'] === 'custom' )
1130
+ do_action( 'wpml_register_single_string', 'Cookie Notice', 'Custom link', $input['see_more_opt']['link'] );
1131
+ }
1132
+
1133
+ add_settings_error( 'cn_cookie_notice_options', 'save_cookie_notice_options', __( 'Settings saved.', 'cookie-notice' ), 'updated' );
1134
+
1135
+ // purge cache on save
1136
+ if ( $is_network )
1137
+ delete_site_transient( 'cookie_notice_compliance_cache' );
1138
+ else
1139
+ delete_transient( 'cookie_notice_compliance_cache' );
1140
+ } elseif ( isset( $_POST['reset_cookie_notice_options'] ) ) {
1141
+ $input = $cn->defaults['general'];
1142
+
1143
+ add_settings_error( 'cn_cookie_notice_options', 'reset_cookie_notice_options', __( 'Settings restored to defaults.', 'cookie-notice' ), 'updated' );
1144
+
1145
+ // network area?
1146
+ if ( $is_network ) {
1147
+ // set app status
1148
+ update_site_option( 'cookie_notice_status', '' );
1149
+
1150
+ // purge cache on save
1151
+ delete_site_transient( 'cookie_notice_compliance_cache' );
1152
+ } else {
1153
+ // set app status
1154
+ update_option( 'cookie_notice_status', '' );
1155
+
1156
+ // purge cache on save
1157
+ delete_transient( 'cookie_notice_compliance_cache' );
1158
+ }
1159
+ }
1160
+
1161
+ return $input;
1162
+ }
1163
+
1164
+ /**
1165
+ * Validate network options.
1166
+ *
1167
+ * @return void
1168
+ */
1169
+ public function validate_network_options() {
1170
+ if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1171
+ return;
1172
+
1173
+ // get main instance
1174
+ $cn = Cookie_Notice();
1175
+
1176
+ // global network page?
1177
+ if ( $cn->is_network_admin() && isset( $_POST['cn-network-settings'] ) ) {
1178
+ // network settings
1179
+ if ( ! empty( $_POST['cookie_notice_options'] ) && check_admin_referer( 'cookie_notice_options-options', '_wpnonce' ) !== false ) {
1180
+ if ( isset( $_POST['save_cookie_notice_options'] ) ) {
1181
+ // validate options
1182
+ $data = $this->validate_options( $_POST['cookie_notice_options'] );
1183
+
1184
+ // check network settings
1185
+ $data['global_override'] = isset( $_POST['cookie_notice_options']['global_override'] );
1186
+ $data['global_cookie'] = isset( $_POST['cookie_notice_options']['global_cookie'] );
1187
+ $data['update_notice_diss'] = $cn->options['general']['update_notice_diss'];
1188
+
1189
+ if ( $data['global_override'] && ! $cn->options['general']['update_notice_diss'] )
1190
+ $data['update_notice'] = true;
1191
+ else
1192
+ $data['update_notice'] = false;
1193
+
1194
+ // update database
1195
+ update_site_option( 'cookie_notice_options', $data );
1196
+
1197
+ // update settings
1198
+ $cn->options['general'] = $cn->multi_array_merge( $cn->defaults['general'], get_site_option( 'cookie_notice_options', $cn->defaults['general'] ) );
1199
+ } elseif ( isset( $_POST['reset_cookie_notice_options'] ) ) {
1200
+ $cn->defaults['general']['update_notice'] = false;
1201
+ $cn->defaults['general']['update_notice_diss'] = false;
1202
+
1203
+ // silent options validation
1204
+ $this->validate_options( $cn->defaults['general'] );
1205
+
1206
+ // update database
1207
+ update_site_option( 'cookie_notice_options', $cn->defaults['general'] );
1208
+
1209
+ // update settings
1210
+ $cn->options['general'] = $cn->defaults['general'];
1211
+ }
1212
+ }
1213
+
1214
+ // update status of cookie compliance
1215
+ $cn->set_status();
1216
+ }
1217
+ }
1218
+
1219
+ /**
1220
+ * Load scripts and styles - admin.
1221
+ *
1222
+ * @return void
1223
+ */
1224
+ public function admin_enqueue_scripts( $page ) {
1225
+ if ( $page === 'toplevel_page_cookie-notice' ) {
1226
+ // get main instance
1227
+ $cn = Cookie_Notice();
1228
+
1229
+ wp_enqueue_script( 'cookie-notice-admin', plugins_url( '../js/admin' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', __FILE__ ), [ 'jquery', 'wp-color-picker' ], $cn->defaults['version'] );
1230
+
1231
+ wp_localize_script(
1232
+ 'cookie-notice-admin',
1233
+ 'cnArgs',
1234
+ [
1235
+ 'ajaxURL' => admin_url( 'admin-ajax.php' ),
1236
+ 'nonce' => wp_create_nonce( 'cn-purge-cache' ),
1237
+ 'network' => (int) $cn->is_network_admin(),
1238
+ 'resetToDefaults' => __( 'Are you sure you want to reset these settings to defaults?', 'cookie-notice' )
1239
+ ]
1240
+ );
1241
+
1242
+ wp_enqueue_style( 'wp-color-picker' );
1243
+ }
1244
+
1245
+ wp_enqueue_style( 'cookie-notice-admin', plugins_url( '../css/admin' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', __FILE__ ) );
1246
+ }
1247
+
1248
+ /**
1249
+ * Load admin style inline, for menu icon only.
1250
+ *
1251
+ * @return void
1252
+ */
1253
+ public function admin_print_styles() {
1254
+ echo '
1255
+ <style>
1256
+ a.toplevel_page_cookie-notice .wp-menu-image {
1257
+ background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAzMjEgMzIxIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zOnNlcmlmPSJodHRwOi8vd3d3LnNlcmlmLmNvbS8iIHN0eWxlPSJmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MjsiPjxwYXRoIGQ9Ik0zMTcuMjc4LDEzMC40NTFjLTAuODEyLC00LjMwMiAtNC4zMDEsLTcuNTYyIC04LjY0MiwtOC4wODFjLTQuMzU0LC0wLjUyMiAtOC41MDYsMS44MjkgLTEwLjMwNyw1LjgyMmMtMy4xNyw3LjAwMyAtMTAuMTMzLDExLjg3MyAtMTguMjA1LDExLjg2NGMtOC45NTUsMC4wMjIgLTE2LjUxNywtNi4wMjEgLTE5LjAzOCwtMTQuMzE1Yy0xLjUyMSwtNS4wNjMgLTYuNzI0LC04LjA2NCAtMTEuODY1LC02Ljg2M2MtMy4xNjMsMC43NDEgLTYuMTU0LDEuMTcyIC05LjEyNSwxLjE3MmMtMjIuMDM5LC0wLjA0MyAtMzkuOTc2LC0xNy45NzkgLTQwLjAxNSwtNDAuMDE5Yy0wLC0yLjk3IDAuNDMsLTUuOTYyIDEuMTY5LC05LjExM2MxLjIxMiwtNS4xNDEgLTEuNzk5LC0xMC4zNTMgLTYuODYsLTExLjg3M2MtOC4yOTUsLTIuNTEzIC0xNC4zMzcsLTEwLjA3NSAtMTQuMzE5LC0xOS4wMjljLTAuMDA5LC04LjA4MiA0Ljg2NCwtMTUuMDM2IDExLjg2NywtMTguMjA4YzMuOTkxLC0xLjc5OCA2LjM0MSwtNS45NjMgNS44MjIsLTEwLjMwNGMtMC41MjIsLTQuMzUxIC0zLjc4MywtNy44NDMgLTguMDg0LC04LjY1MmMtOS41NDMsLTEuNzkyIC0xOS40MjYsLTIuODUyIC0yOS42MTEsLTIuODUyYy04OC4yOTUsMC4wMjIgLTE2MC4wNDMsNzEuNzcgLTE2MC4wNjUsMTYwLjA2NWMwLjAyMiw4OC4yOTUgNzEuNzcsMTYwLjA0MyAxNjAuMDY1LDE2MC4wNjVjODguMjk1LC0wLjAyMiAxNjAuMDQzLC03MS43NyAxNjAuMDY1LC0xNjAuMDY1Yy0wLC0xMC4xODQgLTEuMDYzLC0yMC4wNjcgLTIuODUyLC0yOS42MTRabS01OC4yMjMsMTI4LjYwNGMtMjUuNDAxLDI1LjM4IC02MC4zNTUsNDEuMDY2IC05OC45OSw0MS4wNjZjLTM4LjYzNSwwIC03My41ODgsLTE1LjY4NiAtOTguOTg5LC00MS4wNjZjLTI1LjM4LC0yNS40MDEgLTQxLjA2NiwtNjAuMzU1IC00MS4wNjYsLTk4Ljk5Yy0wLC0zOC42MzUgMTUuNjg2LC03My41ODggNDEuMDY2LC05OC45ODljMjUuNDAxLC0yNS4zOCA2MC4zNTQsLTQxLjA2NiA5OC45ODksLTQxLjA2NmMxLjgwMSwwIDMuNTYsMC4xODkgNS4zNTIsMC4yNjhjLTMuMzQzLDUuODIzIC01LjM0MywxMi41MjcgLTUuMzUyLDE5LjczOGMwLjAxOCwxNC45MzUgOC4zMDQsMjcuNzQyIDIwLjM3OSwzNC41NzVjLTAuMTkyLDEuNzggLTAuMzczLDMuNTYgLTAuMzczLDUuNDRjMC4wMjIsMzMuMTI1IDI2LjkwMyw2MC4wMDcgNjAuMDI1LDYwLjAyNWMxLjg4LDAgMy42NjQsLTAuMTggNS40NDMsLTAuMzY5YzYuODMzLDEyLjA2NSAxOS42MjgsMjAuMzU2IDM0LjU3MiwyMC4zNzhjNy4yMTUsLTAuMDA5IDEzLjkxNiwtMi4wMTEgMTkuNzQxLC01LjM1MmMwLjA4LDEuNzggMC4yNjksMy41NTEgMC4yNjksNS4zNTJjLTAsMzguNjM1IC0xNS42ODYsNzMuNTg5IC00MS4wNjYsOTguOTlabS01OC45NzQsLTE4Ljk1OWMtMCwxMS4wNTIgLTguOTU4LDIwLjAxIC0yMC4wMSwyMC4wMWMtMTEuMDQ4LC0wIC0yMC4wMDUsLTguOTU4IC0yMC4wMDUsLTIwLjAxYy0wLC0xMS4wNDkgOC45NTcsLTIwLjAwNiAyMC4wMDUsLTIwLjAwNmMxMS4wNTIsLTAgMjAuMDEsOC45NTcgMjAuMDEsMjAuMDA2Wm0tODAuMDMxLC0xMC4wMDVjMCw1LjUyNiAtNC40NzksMTAuMDA1IC0xMC4wMDUsMTAuMDA1Yy01LjUyNiwtMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjMgNC40NzksLTEwLjAwMSAxMC4wMDUsLTEwLjAwMWM1LjUyNiwtMCAxMC4wMDUsNC40NzggMTAuMDA1LDEwLjAwMVptMTQwLjA1NSwtMjAuMDA2YzAsNS41MjYgLTQuNDc5LDEwLjAwNSAtMTAuMDA1LDEwLjAwNWMtNS41MjUsMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjYgNC40OCwtMTAuMDA1IDEwLjAwNSwtMTAuMDA1YzUuNTI2LDAgMTAuMDA1LDQuNDc5IDEwLjAwNSwxMC4wMDVabS0xNjAuMDY0LC01MC4wMmMtMCwxMS4wNDggLTguOTU3LDIwLjAwNiAtMjAuMDEsMjAuMDA2Yy0xMS4wNDgsMCAtMjAuMDA1LC04Ljk1OCAtMjAuMDA1LC0yMC4wMDZjLTAsLTExLjA1MiA4Ljk1NywtMjAuMDEgMjAuMDA1LC0yMC4wMWMxMS4wNTMsMCAyMC4wMSw4Ljk1OCAyMC4wMSwyMC4wMVptODAuMDMsMTAuMDA1YzAsNS41MjMgLTQuNDc4LDEwLjAwMSAtMTAuMDAxLDEwLjAwMWMtNS41MjYsMCAtMTAuMDA1LC00LjQ3OCAtMTAuMDA1LC0xMC4wMDFjMCwtNS41MjYgNC40NzksLTEwLjAwNSAxMC4wMDUsLTEwLjAwNWM1LjUyMywwIDEwLjAwMSw0LjQ3OSAxMC4wMDEsMTAuMDA1Wm0xMTUuNDkzLC02OS40MDZjMCw1LjUyNiAtNC40NzksMTAuMDA1IC0xMC4wMDUsMTAuMDA1Yy01LjUyNiwtMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjYgNC40NzksLTEwLjAwNSAxMC4wMDUsLTEwLjAwNWM1LjUyNiwtMCAxMC4wMDUsNC40NzkgMTAuMDA1LDEwLjAwNVptLTM1LjUyMywtMTkuODc0Yy0wLDExLjUwMyAtOS4zMjUsMjAuODI4IC0yMC44MjgsMjAuODI4Yy0xMS41MDQsLTAgLTIwLjgyOSwtOS4zMjUgLTIwLjgyOSwtMjAuODI4Yy0wLC0xMS41MDMgOS4zMjUsLTIwLjgyOCAyMC44MjksLTIwLjgyOGMxMS41MDMsLTAgMjAuODI4LDkuMzI1IDIwLjgyOCwyMC44MjhabS0xMTkuOTg1LC0wLjc1OWMtMCwxMS4wNTIgLTguOTU3LDIwLjAxIC0yMC4wMDYsMjAuMDFjLTExLjA1MiwtMCAtMjAuMDA5LC04Ljk1OCAtMjAuMDA5LC0yMC4wMWMtMCwtMTEuMDQ4IDguOTU3LC0yMC4wMDYgMjAuMDA5LC0yMC4wMDZjMTEuMDQ5LC0wIDIwLjAwNiw4Ljk1OCAyMC4wMDYsMjAuMDA2WiIgc3R5bGU9ImZpbGw6I2ZmZjtmaWxsLXJ1bGU6bm9uemVybzsiLz48L3N2Zz4=);
1258
+ background-position: center center;
1259
+ background-repeat: no-repeat;
1260
+ background-size: 18px auto;
1261
+ }
1262
+ </style>
1263
+ ';
1264
+ }
1265
+
1266
+ /**
1267
+ * Register WPML (>= 3.2) strings if needed.
1268
+ *
1269
+ * @global object $wpdb
1270
+ *
1271
+ * @return void
1272
+ */
1273
+ private function register_wpml_strings() {
1274
+ // get main instance
1275
+ $cn = Cookie_Notice();
1276
+
1277
+ global $wpdb;
1278
+
1279
+ // prepare strings
1280
+ $strings = [
1281
+ 'Message in the notice' => $cn->options['general']['message_text'],
1282
+ 'Button text' => $cn->options['general']['accept_text'],
1283
+ 'Refuse button text' => $cn->options['general']['refuse_text'],
1284
+ 'Revoke message text' => $cn->options['general']['revoke_message_text'],
1285
+ 'Revoke button text' => $cn->options['general']['revoke_text'],
1286
+ 'Privacy policy text' => $cn->options['general']['see_more_opt']['text'],
1287
+ 'Custom link' => $cn->options['general']['see_more_opt']['link']
1288
+ ];
1289
+
1290
+ // get query results
1291
+ $results = $wpdb->get_col( $wpdb->prepare( "SELECT name FROM " . $wpdb->prefix . "icl_strings WHERE context = %s", 'Cookie Notice' ) );
1292
+
1293
+ // check results
1294
+ foreach( $strings as $string => $value ) {
1295
+ // string does not exist?
1296
+ if ( ! in_array( $string, $results, true ) ) {
1297
+ // register string
1298
+ do_action( 'wpml_register_single_string', 'Cookie Notice', $string, $value );
1299
+ }
1300
+ }
1301
+ }
1302
+
1303
+ /**
1304
+ * Display errors and notices.
1305
+ *
1306
+ * @global string $pagenow
1307
+ *
1308
+ * @return void
1309
+ */
1310
+ public function settings_errors() {
1311
+ global $pagenow;
1312
+
1313
+ // force display notices in top menu settings page
1314
+ if ( $pagenow == 'options-general.php' )
1315
+ return;
1316
+
1317
+ settings_errors( 'cn_cookie_notice_options' );
1318
+ }
1319
+
1320
+ /**
1321
+ * Save compliance config caching.
1322
+ *
1323
+ * @return void
1324
+ */
1325
+ public function ajax_purge_cache() {
1326
+ if ( ! check_ajax_referer( 'cn-purge-cache', 'nonce' ) )
1327
+ echo false;
1328
+
1329
+ if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1330
+ echo false;
1331
+
1332
+ if ( Cookie_Notice()->is_network_admin() )
1333
+ delete_site_transient( 'cookie_notice_compliance_cache' );
1334
+ else
1335
+ delete_transient( 'cookie_notice_compliance_cache' );
1336
+
1337
+ echo true;
1338
+ exit;
1339
+ }
1340
  }
includes/welcome-api.php CHANGED
@@ -6,31 +6,27 @@ if ( ! defined( 'ABSPATH' ) )
6
 
7
  /**
8
  * Cookie_Notice_Welcome_API class.
9
- *
10
  * @class Cookie_Notice_Welcome_API
11
  */
12
  class Cookie_Notice_Welcome_API {
13
 
14
- // api urls
15
- private $account_api_url = 'https://account-api.hu-manity.co';
16
- private $designer_api_url = 'https://designer-api.hu-manity.co';
17
- private $transactional_api_url = 'https://transactional-api.hu-manity.co';
18
- private $x_api_key = 'hudft60djisdusdjwek';
19
-
20
  /**
21
  * Constructor.
22
  *
23
  * @return void
24
  */
25
  public function __construct() {
26
- add_action( 'wp_ajax_cn_api_request', array( $this, 'api_request' ) );
27
- // cron job
28
  add_action( 'init', [ $this, 'check_cron' ] );
29
  add_action( 'cookie_notice_get_app_analytics', [ $this, 'get_app_analytics' ] );
 
30
  }
31
 
32
  /**
33
- * Ajax API request
 
 
34
  */
35
  public function api_request() {
36
  if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
@@ -45,43 +41,52 @@ class Cookie_Notice_Welcome_API {
45
  if ( ( $_POST['request'] === 'payment' && ! empty( $_POST['cn_payment_nonce'] ) && ! wp_verify_nonce( $_POST['cn_payment_nonce'], 'cn_api_payment' ) ) || ( ! empty( $_POST['cn_nonce'] ) && ! wp_verify_nonce( $_POST['cn_nonce'], 'cn_api_' . $_POST['request'] ) ) )
46
  wp_die( __( 'You do not have permission to access this page.', 'cookie-notice' ) );
47
 
48
- $request = in_array( $_POST['request'], array( 'register', 'login', 'configure', 'select_plan', 'payment', 'get_bt_init_token', 'use_license' ), true ) ? $_POST['request'] : '';
49
- $errors = array();
50
  $response = false;
51
 
52
  if ( ! $request )
53
  return false;
54
 
 
 
 
55
  // get site language
56
  $locale = get_locale();
57
  $locale_code = explode( '_', $locale );
58
 
 
 
 
59
  // get app token data
60
- $data_token = get_transient( 'cookie_notice_app_token' );
61
- $api_token = ! empty( $data_token->token ) ? $data_token->token : '';
62
- $admin_id = ! empty( $data_token->email ) ? $data_token->email : '';
63
- $app_id = Cookie_Notice()->options['general']['app_id'];
 
 
 
64
 
65
- $params = array();
66
 
67
- switch ($request) {
68
- case 'use_license' :
69
  $subscriptionID = (int) $_POST['subscriptionID'];
70
 
71
- $result = $this->request( 'assign_subscription',
72
- array(
73
- 'AppID' => $app_id,
74
- 'subscriptionID' => $subscriptionID
75
- )
 
76
  );
77
 
78
  // errors?
79
  if ( ! empty( $result->message ) ) {
80
- $response = array( 'error' => $result->message );
81
  break;
82
- } else {
83
  $response = $result;
84
- };
85
 
86
  break;
87
 
@@ -90,11 +95,11 @@ class Cookie_Notice_Welcome_API {
90
 
91
  // is token available?
92
  if ( ! empty( $result->token ) )
93
- $response = array( 'token' => $result->token );
94
  break;
95
 
96
  case 'payment':
97
- $error = array( 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) );
98
 
99
  // empty data?
100
  if ( empty( $_POST['payment_nonce'] ) || empty( $_POST['plan'] ) || empty( $_POST['method'] ) ) {
@@ -103,7 +108,7 @@ class Cookie_Notice_Welcome_API {
103
  }
104
 
105
  // validate plan and payment method
106
- $available_plans = array(
107
  'compliance_monthly_notrial',
108
  'compliance_monthly_5',
109
  'compliance_monthly_10',
@@ -112,49 +117,49 @@ class Cookie_Notice_Welcome_API {
112
  'compliance_yearly_5',
113
  'compliance_yearly_10',
114
  'compliance_yearly_20'
115
- );
116
 
117
  $plan = in_array( $_POST['plan'], $available_plans, true ) ? $_POST['plan'] : false;
118
- $method = in_array( $_POST['method'], array( 'credit_card', 'paypal' ), true ) ? $_POST['method'] : false;
119
 
120
  // valid plan and payment method?
121
  if ( empty( $plan ) || empty( $method ) ) {
122
- $response = array( 'error' => __( 'Empty plan or payment method data.', 'cookie-notice' ) );
123
  break;
124
  }
125
 
126
- $result = $this->request( 'get_customer',
127
- array(
128
- 'AppID' => $app_id,
129
- 'PlanId' => $plan
130
- )
 
131
  );
132
 
133
  // user found?
134
  if ( ! empty( $result->id ) ) {
135
  $customer = $result;
136
- // create user
137
  } else {
138
  $result = $this->request(
139
- 'create_customer',
140
- array(
141
- 'AppID' => $app_id,
142
- 'AdminID' => $admin_id, // remove later - AdminID from API response
143
- 'PlanId' => $plan,
144
- 'paymentMethodNonce' => sanitize_text_field( $_POST['payment_nonce'] )
145
- )
146
  );
147
 
148
- if ( ! empty( $result->success ) ) {
149
  $customer = $result->customer;
150
- } else {
151
  $customer = $result;
152
- }
153
  }
154
 
155
  // user created/received?
156
  if ( empty( $customer->id ) ) {
157
- $response = array( 'error' => __( 'Unable to create customer data.', 'cookie-notice' ) );
158
  break;
159
  }
160
 
@@ -165,10 +170,10 @@ class Cookie_Notice_Welcome_API {
165
  $identifier = isset( $_POST['cn_payment_identifier'] ) ? sanitize_text_field( $_POST['cn_payment_identifier'] ) : '';
166
 
167
  // customer available payment methods
168
- $payment_methods = ! empty( $customer->paymentMethods ) ? $customer->paymentMethods : array();
169
-
170
- $paypal_methods = array();
171
- $cc_methods = array();
172
 
173
  // try to find payment method
174
  if ( ! empty( $payment_methods ) && is_array( $payment_methods ) ) {
@@ -179,7 +184,7 @@ class Cookie_Notice_Welcome_API {
179
 
180
  if ( $pm->email === $identifier )
181
  $payment_method = $pm;
182
- // credit card
183
  } else {
184
  $cc_methods[] = $pm;
185
 
@@ -192,35 +197,35 @@ class Cookie_Notice_Welcome_API {
192
  // if payment method was not identified, create it
193
  if ( ! $payment_method ) {
194
  $result = $this->request(
195
- 'create_payment_method',
196
- array(
197
- 'AppID' => $app_id,
198
- 'paymentMethodNonce' => sanitize_text_field( $_POST['payment_nonce'] )
199
- )
200
  );
201
-
202
  // payment method created successfully?
203
  if ( ! empty( $result->success ) ) {
204
  $payment_method = $result->paymentMethod;
205
  } else {
206
- $response = array( 'error' => __( 'Unable to create payment mehotd.', 'cookie-notice' ) );
207
  break;
208
  }
209
  }
210
 
211
  if ( ! isset( $payment_method->token ) ) {
212
- $response = array( 'error' => __( 'No payment method token.', 'cookie-notice' ) );
213
  break;
214
  }
215
 
216
  // @todo: check if subscribtion exists
217
  $subscription = $this->request(
218
- 'create_subscription',
219
- array(
220
- 'AppID' => $app_id,
221
- 'PlanId' => $plan,
222
- 'paymentMethodToken' => $payment_method->token
223
- )
224
  );
225
 
226
  // subscription assigned?
@@ -240,37 +245,36 @@ class Cookie_Notice_Welcome_API {
240
  $language = ! empty( $_POST['language'] ) ? sanitize_text_field( $_POST['language'] ) : 'en';
241
 
242
  if ( ! $terms ) {
243
- $response = array( 'error' => __( "Please accept the Terms of Service to proceed.", 'cookie-notice' ) );
244
  break;
245
  }
246
 
247
  if ( ! $email ) {
248
- $response = array( 'error' => __( 'Email is not allowed to be empty.', 'cookie-notice' ) );
249
  break;
250
  }
251
 
252
  if ( ! $pass || ! is_string( $pass ) ) {
253
- $response = array( 'error' => __( 'Password is not allowed to be empty.', 'cookie-notice' ) );
254
  break;
255
  }
256
 
257
  if ( $pass !== $pass2 ) {
258
- $response = array( 'error' => __( "Passwords do not match.", 'cookie-notice' ) );
259
  break;
260
  }
261
 
262
- $params = array(
263
- 'AdminID' => $email,
264
- 'Password' => $pass,
265
- 'Language' => $language
266
- );
267
 
268
- $response = $this->request( $request, $params );
269
 
270
  // errors?
271
- if ( ! empty( $response->error ) ) {
272
  break;
273
- }
274
 
275
  // errors?
276
  if ( ! empty( $response->message ) ) {
@@ -279,31 +283,34 @@ class Cookie_Notice_Welcome_API {
279
  }
280
 
281
  // ok, so log in now
282
- $params = array(
283
- 'AdminID' => $email,
284
- 'Password' => $pass
285
- );
286
 
287
  $response = $this->request( 'login', $params );
288
 
289
  // errors?
290
- if ( ! empty( $response->error ) ) {
291
  break;
292
- }
293
 
294
  // errors?
295
  if ( ! empty( $response->message ) ) {
296
  $response->error = $response->message;
297
  break;
298
  }
 
299
  // token in response?
300
  if ( empty( $response->data->token ) ) {
301
- $response = array( 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) );
302
  break;
303
  }
304
 
305
  // set token
306
- set_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
 
 
 
307
 
308
  // multisite?
309
  if ( is_multisite() ) {
@@ -319,10 +326,10 @@ class Cookie_Notice_Welcome_API {
319
  }
320
 
321
  // create new app, no need to check existing
322
- $params = array(
323
- 'DomainName' => $site_title,
324
- 'DomainUrl' => $site_url,
325
- );
326
 
327
  if ( ! empty( $site_description ) )
328
  $params['DomainDescription'] = $site_description;
@@ -337,26 +344,38 @@ class Cookie_Notice_Welcome_API {
337
 
338
  // data in response?
339
  if ( empty( $response->data->AppID ) || empty( $response->data->SecretKey ) ) {
340
- $response = array( 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) );
341
  break;
342
  } else {
343
  $app_id = $response->data->AppID;
344
  $secret_key = $response->data->SecretKey;
345
  }
346
 
347
- // update options: app ID and secret key
348
- Cookie_Notice()->options['general'] = wp_parse_args( array( 'app_id' => $app_id, 'app_key' => $secret_key ), Cookie_Notice()->options['general'] );
 
 
 
 
 
349
 
350
- update_option( 'cookie_notice_options', Cookie_Notice()->options['general'] );
 
351
 
352
- // purge cache
353
- delete_transient( 'cookie_notice_compliance_cache' );
 
 
 
 
 
354
 
355
- // get options
356
- $app_config = get_transient( 'cookie_notice_app_config' );
 
357
 
358
  // create quick config
359
- $params = ! empty( $app_config ) && is_array( $app_config ) ? $app_config : array();
360
 
361
  // cast to objects
362
  if ( $params ) {
@@ -378,15 +397,15 @@ class Cookie_Notice_Welcome_API {
378
 
379
  // add translations if needed
380
  if ( $locale_code[0] !== 'en' )
381
- $params['Languages'] = array( $locale_code[0] );
382
 
383
  $response = $this->request( 'quick_config', $params );
384
 
385
  if ( $response->status === 200 ) {
386
  // notify publish app
387
- $params = array(
388
- 'AppID' => $app_id
389
- );
390
 
391
  $response = $this->request( 'notify_app', $params );
392
 
@@ -394,15 +413,20 @@ class Cookie_Notice_Welcome_API {
394
  $response = true;
395
 
396
  // update app status
397
- update_option( 'cookie_notice_status', 'active' );
 
 
 
398
  } else {
399
  // update app status
400
- update_option( 'cookie_notice_status', 'pending' );
 
 
 
401
 
402
  // errors?
403
- if ( ! empty( $response->error ) ) {
404
  break;
405
- }
406
 
407
  // errors?
408
  if ( ! empty( $response->message ) ) {
@@ -412,7 +436,10 @@ class Cookie_Notice_Welcome_API {
412
  }
413
  } else {
414
  // update app status
415
- update_option( 'cookie_notice_status', 'pending' );
 
 
 
416
 
417
  // errors?
418
  if ( ! empty( $response->error ) ) {
@@ -434,26 +461,25 @@ class Cookie_Notice_Welcome_API {
434
  $pass = ! empty( $_POST['pass'] ) ? $_POST['pass'] : '';
435
 
436
  if ( ! $email ) {
437
- $response = array( 'error' => __( 'Email is not allowed to be empty.', 'cookie-notice' ) );
438
  break;
439
  }
440
 
441
  if ( ! $pass ) {
442
- $response = array( 'error' => __( 'Password is not allowed to be empty.', 'cookie-notice' ) );
443
  break;
444
  }
445
 
446
- $params = array(
447
- 'AdminID' => $email,
448
- 'Password' => $pass
449
- );
450
 
451
  $response = $this->request( $request, $params );
452
 
453
  // errors?
454
- if ( ! empty( $response->error ) ) {
455
  break;
456
- }
457
 
458
  // errors?
459
  if ( ! empty( $response->message ) ) {
@@ -463,15 +489,18 @@ class Cookie_Notice_Welcome_API {
463
 
464
  // token in response?
465
  if ( empty( $response->data->token ) ) {
466
- $response = array( 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) );
467
  break;
468
  }
469
 
470
  // set token
471
- set_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
 
 
 
472
 
473
- // get apps and check if one for the current domain already exists
474
- $response = $this->request( 'list_apps', array() );
475
 
476
  // errors?
477
  if ( ! empty( $response->message ) ) {
@@ -479,7 +508,7 @@ class Cookie_Notice_Welcome_API {
479
  break;
480
  }
481
 
482
- $apps_list = array();
483
  $app_exists = false;
484
 
485
  // multisite?
@@ -500,7 +529,7 @@ class Cookie_Notice_Welcome_API {
500
  $apps_list = (array) $response->data;
501
 
502
  foreach ( $apps_list as $index => $app ) {
503
- $site_without_http = trim( str_replace( array( 'http://', 'https://' ), '', $site_url ), '/' );
504
 
505
  if ( $app->DomainUrl === $site_without_http ) {
506
  $app_exists = $app;
@@ -512,12 +541,11 @@ class Cookie_Notice_Welcome_API {
512
 
513
  // if no app, create one
514
  if ( ! $app_exists ) {
515
-
516
  // create new app
517
- $params = array(
518
- 'DomainName' => $site_title,
519
- 'DomainUrl' => $site_url,
520
- );
521
 
522
  if ( ! empty( $site_description ) )
523
  $params['DomainDescription'] = $site_description;
@@ -535,16 +563,16 @@ class Cookie_Notice_Welcome_API {
535
 
536
  // check if we have the valid app data
537
  if ( empty( $app_exists->AppID ) || empty( $app_exists->SecretKey ) ) {
538
- $response = array( 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) );
539
  break;
540
  }
541
 
542
  // get subscriptions
543
- $subscriptions = array();
544
 
545
- $params = array(
546
  'AppID' => $app_exists->AppID
547
- );
548
 
549
  $response = $this->request( 'get_subscriptions', $params );
550
 
@@ -552,38 +580,49 @@ class Cookie_Notice_Welcome_API {
552
  if ( ! empty( $response->error ) ) {
553
  $response->error = $response->error;
554
  break;
555
- } else {
556
  $subscriptions = map_deep( (array) $response->data, 'sanitize_text_field' );
557
- }
558
 
559
  // set subscriptions data
560
- set_transient( 'cookie_notice_app_subscriptions', $subscriptions, 24 * HOUR_IN_SECONDS );
 
 
 
561
 
562
  // update options: app ID and secret key
563
- Cookie_Notice()->options['general'] = wp_parse_args( array( 'app_id' => $app_exists->AppID, 'app_key' => $app_exists->SecretKey ), Cookie_Notice()->options['general'] );
564
 
565
- update_option( 'cookie_notice_options', Cookie_Notice()->options['general'] );
 
566
 
567
- // purge cache
568
- delete_transient( 'cookie_notice_compliance_cache' );
 
 
 
 
 
 
 
 
569
 
570
  // create quick config
571
- $params = array(
572
- 'AppID' => $app_exists->AppID,
573
- 'DefaultLanguage' => 'en',
574
- );
575
 
576
  // add translations if needed
577
  if ( $locale_code[0] !== 'en' )
578
- $params['Languages'] = array( $locale_code[0] );
579
 
580
  $response = $this->request( 'quick_config', $params );
581
 
582
  if ( $response->status === 200 ) {
583
  // @todo notify publish app
584
- $params = array(
585
  'AppID' => $app_exists->AppID
586
- );
587
 
588
  $response = $this->request( 'notify_app', $params );
589
 
@@ -591,15 +630,20 @@ class Cookie_Notice_Welcome_API {
591
  $response = true;
592
 
593
  // update app status
594
- update_option( 'cookie_notice_status', 'active' );
 
 
 
595
  } else {
596
  // update app status
597
- update_option( 'cookie_notice_status', 'pending' );
 
 
 
598
 
599
  // errors?
600
- if ( ! empty( $response->error ) ) {
601
  break;
602
- }
603
 
604
  // errors?
605
  if ( ! empty( $response->message ) ) {
@@ -609,7 +653,10 @@ class Cookie_Notice_Welcome_API {
609
  }
610
  } else {
611
  // update app status
612
- update_option( 'cookie_notice_status', 'pending' );
 
 
 
613
 
614
  // errors?
615
  if ( ! empty( $response->error ) ) {
@@ -625,13 +672,12 @@ class Cookie_Notice_Welcome_API {
625
  }
626
 
627
  // all ok, return subscriptions
628
- $response = (object) array();
629
  $response->subscriptions = $subscriptions;
630
-
631
  break;
632
 
633
  case 'configure':
634
- $fields = array(
635
  'cn_position',
636
  'cn_color_primary',
637
  'cn_color_background',
@@ -642,21 +688,23 @@ class Cookie_Notice_Welcome_API {
642
  'cn_laws',
643
  'cn_naming',
644
  'cn_privacy_paper',
645
- 'cn_privacy_contact',
646
- );
647
 
648
- $options = array();
649
 
650
  // loop through potential config form fields
651
  foreach ( $fields as $field ) {
652
- switch ($field) {
653
  case 'cn_position':
654
  // sanitize position
655
  $position = isset( $_POST[$field] ) ? sanitize_key( $_POST[$field] ) : '';
656
 
657
  // valid position?
658
- if ( in_array( $position, array( 'bottom', 'top', 'left', 'right', 'center' ), true ) )
659
  $options['design']['position'] = $position;
 
 
660
  break;
661
 
662
  case 'cn_color_primary':
@@ -666,6 +714,8 @@ class Cookie_Notice_Welcome_API {
666
  // valid color?
667
  if ( empty( $color ) )
668
  $options['design']['primaryColor'] = '#20c19e';
 
 
669
  break;
670
 
671
  case 'cn_color_background':
@@ -675,6 +725,8 @@ class Cookie_Notice_Welcome_API {
675
  // valid color?
676
  if ( empty( $color ) )
677
  $options['design']['bannerColor'] = '#ffffff';
 
 
678
  break;
679
 
680
  case 'cn_color_border':
@@ -684,6 +736,8 @@ class Cookie_Notice_Welcome_API {
684
  // valid color?
685
  if ( empty( $color ) )
686
  $options['design']['borderColor'] = '#5e6a74';
 
 
687
  break;
688
 
689
  case 'cn_color_text':
@@ -693,6 +747,8 @@ class Cookie_Notice_Welcome_API {
693
  // valid color?
694
  if ( empty( $color ) )
695
  $options['design']['textColor'] = '#434f58';
 
 
696
  break;
697
 
698
  case 'cn_color_heading':
@@ -702,6 +758,8 @@ class Cookie_Notice_Welcome_API {
702
  // valid color?
703
  if ( empty( $color ) )
704
  $options['design']['headingColor'] = '#434f58';
 
 
705
  break;
706
 
707
  case 'cn_color_button_text':
@@ -711,17 +769,19 @@ class Cookie_Notice_Welcome_API {
711
  // valid color?
712
  if ( empty( $color ) )
713
  $options['design']['btnTextColor'] = '#ffffff';
 
 
714
  break;
715
 
716
  case 'cn_laws':
717
- $new_options = array();
718
 
719
  // any data?
720
- if ( is_array( $_POST[$field] ) && ! empty( $_POST[$field] ) ) {
721
  $options['laws'] = array_map( 'sanitize_text_field', $_POST[$field] );
722
 
723
  foreach ( $options['laws'] as $law ) {
724
- if ( in_array( $law, array( 'gdpr', 'ccpa' ), true ) )
725
  $new_options[$law] = true;
726
  }
727
  }
@@ -743,33 +803,32 @@ class Cookie_Notice_Welcome_API {
743
 
744
  case 'cn_naming':
745
  $naming = isset( $_POST[$field] ) ? (int) $_POST[$field] : 1;
746
- $naming = in_array( $naming, array( 1, 2, 3 ) ) ? $naming : 1;
747
 
748
- // English only for now
749
- $level_names = array(
750
- 1 => array(
751
  1 => 'Silver',
752
  2 => 'Gold',
753
  3 => 'Platinum'
754
- ),
755
- 2 => array(
756
  1 => 'Private',
757
  2 => 'Balanced',
758
  3 => 'Personalized'
759
- ),
760
- 3 => array(
761
  1 => 'Reject All',
762
  2 => 'Accept Some',
763
  3 => 'Accept All'
764
- )
765
- );
766
-
767
- $options['text'] = array(
768
- 'levelNameText_1' => $level_names[$naming][1],
769
- 'levelNameText_2' => $level_names[$naming][2],
770
- 'levelNameText_3' => $level_names[$naming][3]
771
- );
772
-
773
  break;
774
 
775
  case 'cn_privacy_paper':
@@ -783,8 +842,10 @@ class Cookie_Notice_Welcome_API {
783
  }
784
 
785
  // set options
786
- set_transient( 'cookie_notice_app_config', $options, 24 * HOUR_IN_SECONDS );
787
-
 
 
788
  break;
789
 
790
  case 'select_plan':
@@ -798,194 +859,205 @@ class Cookie_Notice_Welcome_API {
798
  /**
799
  * API request.
800
  *
801
- * @param string $action The requested action.
802
- * @param array $_data Parameters for the API action.
803
- * @return false|object
804
  */
805
- private function request( $request = '', $params = '' ) {
806
- $api_args = array(
807
- 'timeout' => 60,
808
- 'sslverify' => false,
809
- 'headers' => array( 'x-api-key' => $this->x_api_key )
810
- );
811
- $api_params = array();
 
 
 
 
 
812
  $json = false;
813
 
 
 
 
814
  // get app token data
815
- $data_token = get_transient( 'cookie_notice_app_token' );
 
 
 
 
816
  $api_token = ! empty( $data_token->token ) ? $data_token->token : '';
817
- $admin_id = ! empty( $data_token->email ) ? $data_token->email : '';
818
 
819
- switch ($request) {
820
  case 'register':
821
- $api_url = $this->account_api_url . '/api/account/account/registration';
822
  $api_args['method'] = 'POST';
823
  break;
824
 
825
  case 'login':
826
- $api_url = $this->account_api_url . '/api/account/account/login';
827
  $api_args['method'] = 'POST';
828
  break;
829
 
830
  case 'list_apps':
831
- $api_url = $this->account_api_url . '/api/account/app/list';
832
  $api_args['method'] = 'GET';
833
  $api_args['headers'] = array_merge(
834
- $api_args['headers'],
835
- array(
836
- 'Authorization' => 'Bearer ' . $api_token
837
- )
838
  );
839
  break;
840
 
841
  case 'app_create':
842
- $api_url = $this->account_api_url . '/api/account/app/add';
843
  $api_args['method'] = 'POST';
844
  $api_args['headers'] = array_merge(
845
- $api_args['headers'],
846
- array(
847
- 'Authorization' => 'Bearer ' . $api_token
848
- )
849
  );
850
  break;
851
 
852
  case 'get_analytics':
853
- $api_url = $this->transactional_api_url . '/api/transactional/analytics/analytics-data';
854
  $api_args['method'] = 'GET';
855
  $api_args['headers'] = array_merge(
856
- $api_args['headers'],
857
- array(
858
- 'app-id' => Cookie_Notice()->options['general']['app_id'],
859
- 'app-secret-key' => Cookie_Notice()->options['general']['app_key'],
860
- )
861
  );
862
  break;
863
 
864
  case 'get_config':
865
- $api_url = $this->designer_api_url . '/api/designer/user-design-live';
866
  $api_args['method'] = 'GET';
867
  break;
868
 
869
  case 'quick_config':
870
  $json = true;
871
- $api_url = $this->designer_api_url . '/api/designer/user-design/quick';
872
  $api_args['method'] = 'POST';
873
  $api_args['headers'] = array_merge(
874
- $api_args['headers'],
875
- array(
876
- 'Authorization' => 'Bearer ' . $api_token,
877
- 'Content-Type' => 'application/json; charset=utf-8'
878
- )
879
  );
880
  break;
881
 
882
  case 'notify_app':
883
  $json = true;
884
- $api_url = $this->account_api_url . '/api/account/app/notifyAppPublished';
885
  $api_args['method'] = 'POST';
886
  $api_args['headers'] = array_merge(
887
- $api_args['headers'],
888
- array(
889
- 'Authorization' => 'Bearer ' . $api_token,
890
- 'Content-Type' => 'application/json; charset=utf-8'
891
- )
892
  );
893
  break;
894
 
895
  // braintree init token
896
  case 'get_token':
897
- $api_url = $this->account_api_url . '/api/account/braintree';
898
  $api_args['method'] = 'GET';
899
  $api_args['headers'] = array_merge(
900
- $api_args['headers'],
901
- array(
902
- 'Authorization' => 'Bearer ' . $api_token
903
- )
904
  );
905
  break;
906
 
907
  // braintree get customer
908
  case 'get_customer':
909
  $json = true;
910
- $api_url = $this->account_api_url . '/api/account/braintree/findcustomer';
911
  $api_args['method'] = 'POST';
912
  $api_args['data_format'] = 'body';
913
  $api_args['headers'] = array_merge(
914
- $api_args['headers'],
915
- array(
916
- 'Authorization' => 'Bearer ' . $api_token,
917
- 'Content-Type' => 'application/json; charset=utf-8'
918
- )
919
  );
920
  break;
921
 
922
  // braintree create customer in vault
923
  case 'create_customer':
924
  $json = true;
925
- $api_url = $this->account_api_url . '/api/account/braintree/createcustomer';
926
  $api_args['method'] = 'POST';
927
  $api_args['headers'] = array_merge(
928
- $api_args['headers'],
929
- array(
930
- 'Authorization' => 'Bearer ' . $api_token,
931
- 'Content-Type' => 'application/json; charset=utf-8'
932
- )
933
  );
934
  break;
935
 
936
  // braintree get subscriptions
937
  case 'get_subscriptions':
938
  $json = true;
939
- $api_url = $this->account_api_url . '/api/account/braintree/subscriptionlists';
940
  $api_args['method'] = 'POST';
941
  $api_args['headers'] = array_merge(
942
- $api_args['headers'],
943
- array(
944
- 'Authorization' => 'Bearer ' . $api_token,
945
- 'Content-Type' => 'application/json; charset=utf-8'
946
- )
947
  );
948
  break;
949
 
950
  // braintree create subscription
951
  case 'create_subscription':
952
  $json = true;
953
- $api_url = $this->account_api_url . '/api/account/braintree/createsubscription';
954
  $api_args['method'] = 'POST';
955
  $api_args['headers'] = array_merge(
956
- $api_args['headers'],
957
- array(
958
- 'Authorization' => 'Bearer ' . $api_token,
959
- 'Content-Type' => 'application/json; charset=utf-8'
960
- )
961
  );
962
  break;
963
 
964
  // braintree assign subscription
965
  case 'assign_subscription':
966
  $json = true;
967
- $api_url = $this->account_api_url . '/api/account/braintree/assignsubscription';
968
  $api_args['method'] = 'POST';
969
  $api_args['headers'] = array_merge(
970
- $api_args['headers'],
971
- array(
972
- 'Authorization' => 'Bearer ' . $api_token,
973
- 'Content-Type' => 'application/json; charset=utf-8'
974
- )
975
  );
976
  break;
977
 
978
- // braintree create subscription
979
  case 'create_payment_method':
980
  $json = true;
981
- $api_url = $this->account_api_url . '/api/account/braintree/createpaymentmethod';
982
  $api_args['method'] = 'POST';
983
  $api_args['headers'] = array_merge(
984
- $api_args['headers'],
985
- array(
986
- 'Authorization' => 'Bearer ' . $api_token,
987
- 'Content-Type' => 'application/json; charset=utf-8'
988
- )
989
  );
990
  break;
991
  }
@@ -994,6 +1066,8 @@ class Cookie_Notice_Welcome_API {
994
  foreach ( $params as $key => $param ) {
995
  if ( is_object( $param ) )
996
  $api_params[$key] = $param;
 
 
997
  else
998
  $api_params[$key] = sanitize_text_field( $param );
999
  }
@@ -1007,15 +1081,16 @@ class Cookie_Notice_Welcome_API {
1007
  $response = wp_remote_request( $api_url, $api_args );
1008
 
1009
  if ( is_wp_error( $response ) )
1010
- $result = array( 'error' => $response->get_error_message() );
1011
  else {
1012
  $content_type = wp_remote_retrieve_header( $response, 'Content-Type' );
1013
 
1014
- // HTML response, means error
1015
- if ( $content_type == 'text/html' ) {
1016
- $result = array( 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) );
1017
- } else {
1018
  $result = wp_remote_retrieve_body( $response );
 
1019
  // detect json or array
1020
  $result = is_array( $result ) ? $result : json_decode( $result );
1021
  }
@@ -1031,47 +1106,78 @@ class Cookie_Notice_Welcome_API {
1031
  */
1032
  public function check_cron() {
1033
  // compliance acitve only
1034
- if ( Cookie_Notice()->get_status() == 'active' ) {
1035
  if ( ! wp_next_scheduled( 'cookie_notice_get_app_analytics' ) ) {
1036
  // set schedule
1037
  wp_schedule_event( time(), 'hourly', 'cookie_notice_get_app_analytics' ); // hourly
1038
  }
1039
- } elseif ( wp_next_scheduled( 'cookie_notice_get_app_analytics' ) ) {
1040
  wp_clear_scheduled_hook( 'cookie_notice_get_app_analytics' );
1041
- }
1042
  }
1043
 
1044
  /**
1045
- * Get app config
 
 
1046
  */
1047
- public function get_app_analytics() {
1048
- $result = array();
 
1049
 
1050
- $params = array(
1051
- 'AppID' => Cookie_Notice()->options['general']['app_id']
1052
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1053
 
1054
- $response = $this->request( 'get_analytics', $params );
 
 
 
 
 
1055
 
1056
- // echo '<pre>'; print_r( $response ); echo '</pre>'; exit;
1057
  // get analytics
1058
  if ( ! empty( $response->data ) ) {
1059
- $result = ! empty( $response->data ) ? map_deep( (array) $response->data, 'sanitize_text_field' ) : array();
1060
 
1061
  // update app status
1062
  if ( ! empty( $result ) ) {
1063
  // add time updated
1064
  $result['lastUpdated'] = date( 'Y-m-d H:i:s', current_time( 'timestamp', true ) );
1065
 
1066
- update_option( 'cookie_notice_app_analytics', $result, false );
 
 
 
1067
  }
1068
  }
1069
-
1070
- return $result;
1071
  }
1072
 
1073
  /**
1074
- * Get app status
 
 
1075
  */
1076
  public function get_app_status( $app_id ) {
1077
  $result = '';
@@ -1079,17 +1185,18 @@ class Cookie_Notice_Welcome_API {
1079
  if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1080
  return false;
1081
 
1082
- $params = array(
1083
- 'AppID' => $app_id
 
 
 
1084
  );
1085
 
1086
- $response = $this->request( 'get_config', $params );
1087
-
1088
- if ( ! empty( $response->data ) ) {
1089
  $result = 'active';
1090
- } else {
1091
  if ( ! empty( $response->error ) ) {
1092
- if ( $response->error == 'App is not puplised yet' )
1093
  $result = 'pending';
1094
  else
1095
  $result = '';
@@ -1103,13 +1210,13 @@ class Cookie_Notice_Welcome_API {
1103
  * Defines the function used to initial the cURL library.
1104
  *
1105
  * @param string $url To URL to which the request is being made
1106
- * @param string $params The URL query parameters
1107
- * @return string $response The response, if available; otherwise, null
1108
  */
1109
  private function curl( $url, $args ) {
1110
  $curl = curl_init( $url );
1111
 
1112
- $headers = array();
1113
 
1114
  foreach ( $args['headers'] as $header => $value ) {
1115
  $headers[] = $header . ': ' . $value;
@@ -1133,5 +1240,4 @@ class Cookie_Notice_Welcome_API {
1133
 
1134
  return $response;
1135
  }
1136
-
1137
- }
6
 
7
  /**
8
  * Cookie_Notice_Welcome_API class.
9
+ *
10
  * @class Cookie_Notice_Welcome_API
11
  */
12
  class Cookie_Notice_Welcome_API {
13
 
 
 
 
 
 
 
14
  /**
15
  * Constructor.
16
  *
17
  * @return void
18
  */
19
  public function __construct() {
20
+ // actions
 
21
  add_action( 'init', [ $this, 'check_cron' ] );
22
  add_action( 'cookie_notice_get_app_analytics', [ $this, 'get_app_analytics' ] );
23
+ add_action( 'wp_ajax_cn_api_request', [ $this, 'api_request' ] );
24
  }
25
 
26
  /**
27
+ * Ajax API request.
28
+ *
29
+ * @return bool|void
30
  */
31
  public function api_request() {
32
  if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
41
  if ( ( $_POST['request'] === 'payment' && ! empty( $_POST['cn_payment_nonce'] ) && ! wp_verify_nonce( $_POST['cn_payment_nonce'], 'cn_api_payment' ) ) || ( ! empty( $_POST['cn_nonce'] ) && ! wp_verify_nonce( $_POST['cn_nonce'], 'cn_api_' . $_POST['request'] ) ) )
42
  wp_die( __( 'You do not have permission to access this page.', 'cookie-notice' ) );
43
 
44
+ $request = in_array( $_POST['request'], [ 'register', 'login', 'configure', 'select_plan', 'payment', 'get_bt_init_token', 'use_license' ], true ) ? $_POST['request'] : '';
45
+ $errors = [];
46
  $response = false;
47
 
48
  if ( ! $request )
49
  return false;
50
 
51
+ // get main instance
52
+ $cn = Cookie_Notice();
53
+
54
  // get site language
55
  $locale = get_locale();
56
  $locale_code = explode( '_', $locale );
57
 
58
+ // check network
59
+ $network = $cn->is_network_admin();
60
+
61
  // get app token data
62
+ if ( $network )
63
+ $data_token = get_site_transient( 'cookie_notice_app_token' );
64
+ else
65
+ $data_token = get_transient( 'cookie_notice_app_token' );
66
+
67
+ $admin_email = ! empty( $data_token->email ) ? $data_token->email : '';
68
+ $app_id = $cn->options['general']['app_id'];
69
 
70
+ $params = [];
71
 
72
+ switch ( $request ) {
73
+ case 'use_license':
74
  $subscriptionID = (int) $_POST['subscriptionID'];
75
 
76
+ $result = $this->request(
77
+ 'assign_subscription',
78
+ [
79
+ 'AppID' => $app_id,
80
+ 'subscriptionID' => $subscriptionID
81
+ ]
82
  );
83
 
84
  // errors?
85
  if ( ! empty( $result->message ) ) {
86
+ $response = [ 'error' => $result->message ];
87
  break;
88
+ } else
89
  $response = $result;
 
90
 
91
  break;
92
 
95
 
96
  // is token available?
97
  if ( ! empty( $result->token ) )
98
+ $response = [ 'token' => $result->token ];
99
  break;
100
 
101
  case 'payment':
102
+ $error = [ 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
103
 
104
  // empty data?
105
  if ( empty( $_POST['payment_nonce'] ) || empty( $_POST['plan'] ) || empty( $_POST['method'] ) ) {
108
  }
109
 
110
  // validate plan and payment method
111
+ $available_plans = [
112
  'compliance_monthly_notrial',
113
  'compliance_monthly_5',
114
  'compliance_monthly_10',
117
  'compliance_yearly_5',
118
  'compliance_yearly_10',
119
  'compliance_yearly_20'
120
+ ];
121
 
122
  $plan = in_array( $_POST['plan'], $available_plans, true ) ? $_POST['plan'] : false;
123
+ $method = in_array( $_POST['method'], [ 'credit_card', 'paypal' ], true ) ? $_POST['method'] : false;
124
 
125
  // valid plan and payment method?
126
  if ( empty( $plan ) || empty( $method ) ) {
127
+ $response = [ 'error' => __( 'Empty plan or payment method data.', 'cookie-notice' ) ];
128
  break;
129
  }
130
 
131
+ $result = $this->request(
132
+ 'get_customer',
133
+ [
134
+ 'AppID' => $app_id,
135
+ 'PlanId' => $plan
136
+ ]
137
  );
138
 
139
  // user found?
140
  if ( ! empty( $result->id ) ) {
141
  $customer = $result;
142
+ // create user
143
  } else {
144
  $result = $this->request(
145
+ 'create_customer',
146
+ [
147
+ 'AppID' => $app_id,
148
+ 'AdminID' => $admin_email, // remove later - AdminID from API response
149
+ 'PlanId' => $plan,
150
+ 'paymentMethodNonce' => sanitize_text_field( $_POST['payment_nonce'] )
151
+ ]
152
  );
153
 
154
+ if ( ! empty( $result->success ) )
155
  $customer = $result->customer;
156
+ else
157
  $customer = $result;
 
158
  }
159
 
160
  // user created/received?
161
  if ( empty( $customer->id ) ) {
162
+ $response = [ 'error' => __( 'Unable to create customer data.', 'cookie-notice' ) ];
163
  break;
164
  }
165
 
170
  $identifier = isset( $_POST['cn_payment_identifier'] ) ? sanitize_text_field( $_POST['cn_payment_identifier'] ) : '';
171
 
172
  // customer available payment methods
173
+ $payment_methods = ! empty( $customer->paymentMethods ) ? $customer->paymentMethods : [];
174
+
175
+ $paypal_methods = [];
176
+ $cc_methods = [];
177
 
178
  // try to find payment method
179
  if ( ! empty( $payment_methods ) && is_array( $payment_methods ) ) {
184
 
185
  if ( $pm->email === $identifier )
186
  $payment_method = $pm;
187
+ // credit card
188
  } else {
189
  $cc_methods[] = $pm;
190
 
197
  // if payment method was not identified, create it
198
  if ( ! $payment_method ) {
199
  $result = $this->request(
200
+ 'create_payment_method',
201
+ [
202
+ 'AppID' => $app_id,
203
+ 'paymentMethodNonce' => sanitize_text_field( $_POST['payment_nonce'] )
204
+ ]
205
  );
206
+
207
  // payment method created successfully?
208
  if ( ! empty( $result->success ) ) {
209
  $payment_method = $result->paymentMethod;
210
  } else {
211
+ $response = [ 'error' => __( 'Unable to create payment mehotd.', 'cookie-notice' ) ];
212
  break;
213
  }
214
  }
215
 
216
  if ( ! isset( $payment_method->token ) ) {
217
+ $response = [ 'error' => __( 'No payment method token.', 'cookie-notice' ) ];
218
  break;
219
  }
220
 
221
  // @todo: check if subscribtion exists
222
  $subscription = $this->request(
223
+ 'create_subscription',
224
+ [
225
+ 'AppID' => $app_id,
226
+ 'PlanId' => $plan,
227
+ 'paymentMethodToken' => $payment_method->token
228
+ ]
229
  );
230
 
231
  // subscription assigned?
245
  $language = ! empty( $_POST['language'] ) ? sanitize_text_field( $_POST['language'] ) : 'en';
246
 
247
  if ( ! $terms ) {
248
+ $response = [ 'error' => __( 'Please accept the Terms of Service to proceed.', 'cookie-notice' ) ];
249
  break;
250
  }
251
 
252
  if ( ! $email ) {
253
+ $response = [ 'error' => __( 'Email is not allowed to be empty.', 'cookie-notice' ) ];
254
  break;
255
  }
256
 
257
  if ( ! $pass || ! is_string( $pass ) ) {
258
+ $response = [ 'error' => __( 'Password is not allowed to be empty.', 'cookie-notice' ) ];
259
  break;
260
  }
261
 
262
  if ( $pass !== $pass2 ) {
263
+ $response = [ 'error' => __( 'Passwords do not match.', 'cookie-notice' ) ];
264
  break;
265
  }
266
 
267
+ $params = [
268
+ 'AdminID' => $email,
269
+ 'Password' => $pass,
270
+ 'Language' => $language
271
+ ];
272
 
273
+ $response = $this->request( 'register', $params );
274
 
275
  // errors?
276
+ if ( ! empty( $response->error ) )
277
  break;
 
278
 
279
  // errors?
280
  if ( ! empty( $response->message ) ) {
283
  }
284
 
285
  // ok, so log in now
286
+ $params = [
287
+ 'AdminID' => $email,
288
+ 'Password' => $pass
289
+ ];
290
 
291
  $response = $this->request( 'login', $params );
292
 
293
  // errors?
294
+ if ( ! empty( $response->error ) )
295
  break;
 
296
 
297
  // errors?
298
  if ( ! empty( $response->message ) ) {
299
  $response->error = $response->message;
300
  break;
301
  }
302
+
303
  // token in response?
304
  if ( empty( $response->data->token ) ) {
305
+ $response = [ 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
306
  break;
307
  }
308
 
309
  // set token
310
+ if ( $network )
311
+ set_site_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
312
+ else
313
+ set_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
314
 
315
  // multisite?
316
  if ( is_multisite() ) {
326
  }
327
 
328
  // create new app, no need to check existing
329
+ $params = [
330
+ 'DomainName' => $site_title,
331
+ 'DomainUrl' => $site_url
332
+ ];
333
 
334
  if ( ! empty( $site_description ) )
335
  $params['DomainDescription'] = $site_description;
344
 
345
  // data in response?
346
  if ( empty( $response->data->AppID ) || empty( $response->data->SecretKey ) ) {
347
+ $response = [ 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
348
  break;
349
  } else {
350
  $app_id = $response->data->AppID;
351
  $secret_key = $response->data->SecretKey;
352
  }
353
 
354
+ // update options: app id and secret key
355
+ $cn->options['general'] = wp_parse_args( [ 'app_id' => $app_id, 'app_key' => $secret_key ], $cn->options['general'] );
356
+
357
+ if ( $network ) {
358
+ $cn->options['general']['global_override'] = true;
359
+
360
+ update_site_option( 'cookie_notice_options', $cn->options['general'] );
361
 
362
+ // purge cache
363
+ delete_site_transient( 'cookie_notice_compliance_cache' );
364
 
365
+ // get options
366
+ $app_config = get_site_transient( 'cookie_notice_app_config' );
367
+ } else {
368
+ update_option( 'cookie_notice_options', $cn->options['general'] );
369
+
370
+ // purge cache
371
+ delete_transient( 'cookie_notice_compliance_cache' );
372
 
373
+ // get options
374
+ $app_config = get_transient( 'cookie_notice_app_config' );
375
+ }
376
 
377
  // create quick config
378
+ $params = ! empty( $app_config ) && is_array( $app_config ) ? $app_config : [];
379
 
380
  // cast to objects
381
  if ( $params ) {
397
 
398
  // add translations if needed
399
  if ( $locale_code[0] !== 'en' )
400
+ $params['Languages'] = [ $locale_code[0] ];
401
 
402
  $response = $this->request( 'quick_config', $params );
403
 
404
  if ( $response->status === 200 ) {
405
  // notify publish app
406
+ $params = [
407
+ 'AppID' => $app_id
408
+ ];
409
 
410
  $response = $this->request( 'notify_app', $params );
411
 
413
  $response = true;
414
 
415
  // update app status
416
+ if ( $network )
417
+ update_site_option( 'cookie_notice_status', 'active' );
418
+ else
419
+ update_option( 'cookie_notice_status', 'active' );
420
  } else {
421
  // update app status
422
+ if ( $network )
423
+ update_site_option( 'cookie_notice_status', 'pending' );
424
+ else
425
+ update_option( 'cookie_notice_status', 'pending' );
426
 
427
  // errors?
428
+ if ( ! empty( $response->error ) )
429
  break;
 
430
 
431
  // errors?
432
  if ( ! empty( $response->message ) ) {
436
  }
437
  } else {
438
  // update app status
439
+ if ( $network )
440
+ update_site_option( 'cookie_notice_status', 'pending' );
441
+ else
442
+ update_option( 'cookie_notice_status', 'pending' );
443
 
444
  // errors?
445
  if ( ! empty( $response->error ) ) {
461
  $pass = ! empty( $_POST['pass'] ) ? $_POST['pass'] : '';
462
 
463
  if ( ! $email ) {
464
+ $response = [ 'error' => __( 'Email is not allowed to be empty.', 'cookie-notice' ) ];
465
  break;
466
  }
467
 
468
  if ( ! $pass ) {
469
+ $response = [ 'error' => __( 'Password is not allowed to be empty.', 'cookie-notice' ) ];
470
  break;
471
  }
472
 
473
+ $params = [
474
+ 'AdminID' => $email,
475
+ 'Password' => $pass
476
+ ];
477
 
478
  $response = $this->request( $request, $params );
479
 
480
  // errors?
481
+ if ( ! empty( $response->error ) )
482
  break;
 
483
 
484
  // errors?
485
  if ( ! empty( $response->message ) ) {
489
 
490
  // token in response?
491
  if ( empty( $response->data->token ) ) {
492
+ $response = [ 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
493
  break;
494
  }
495
 
496
  // set token
497
+ if ( $network )
498
+ set_site_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
499
+ else
500
+ set_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
501
 
502
+ // get apps and check if one for the current domain already exists
503
+ $response = $this->request( 'list_apps', [] );
504
 
505
  // errors?
506
  if ( ! empty( $response->message ) ) {
508
  break;
509
  }
510
 
511
+ $apps_list = [];
512
  $app_exists = false;
513
 
514
  // multisite?
529
  $apps_list = (array) $response->data;
530
 
531
  foreach ( $apps_list as $index => $app ) {
532
+ $site_without_http = trim( str_replace( [ 'http://', 'https://' ], '', $site_url ), '/' );
533
 
534
  if ( $app->DomainUrl === $site_without_http ) {
535
  $app_exists = $app;
541
 
542
  // if no app, create one
543
  if ( ! $app_exists ) {
 
544
  // create new app
545
+ $params = [
546
+ 'DomainName' => $site_title,
547
+ 'DomainUrl' => $site_url,
548
+ ];
549
 
550
  if ( ! empty( $site_description ) )
551
  $params['DomainDescription'] = $site_description;
563
 
564
  // check if we have the valid app data
565
  if ( empty( $app_exists->AppID ) || empty( $app_exists->SecretKey ) ) {
566
+ $response = [ 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
567
  break;
568
  }
569
 
570
  // get subscriptions
571
+ $subscriptions = [];
572
 
573
+ $params = [
574
  'AppID' => $app_exists->AppID
575
+ ];
576
 
577
  $response = $this->request( 'get_subscriptions', $params );
578
 
580
  if ( ! empty( $response->error ) ) {
581
  $response->error = $response->error;
582
  break;
583
+ } else
584
  $subscriptions = map_deep( (array) $response->data, 'sanitize_text_field' );
 
585
 
586
  // set subscriptions data
587
+ if ( $network )
588
+ set_site_transient( 'cookie_notice_app_subscriptions', $subscriptions, 24 * HOUR_IN_SECONDS );
589
+ else
590
+ set_transient( 'cookie_notice_app_subscriptions', $subscriptions, 24 * HOUR_IN_SECONDS );
591
 
592
  // update options: app ID and secret key
593
+ $cn->options['general'] = wp_parse_args( [ 'app_id' => $app_exists->AppID, 'app_key' => $app_exists->SecretKey ], $cn->options['general'] );
594
 
595
+ if ( $network ) {
596
+ $cn->options['general']['global_override'] = true;
597
 
598
+ update_site_option( 'cookie_notice_options', $cn->options['general'] );
599
+
600
+ // purge cache
601
+ delete_site_transient( 'cookie_notice_compliance_cache' );
602
+ } else {
603
+ update_option( 'cookie_notice_options', $cn->options['general'] );
604
+
605
+ // purge cache
606
+ delete_transient( 'cookie_notice_compliance_cache' );
607
+ }
608
 
609
  // create quick config
610
+ $params = [
611
+ 'AppID' => $app_exists->AppID,
612
+ 'DefaultLanguage' => 'en'
613
+ ];
614
 
615
  // add translations if needed
616
  if ( $locale_code[0] !== 'en' )
617
+ $params['Languages'] = [ $locale_code[0] ];
618
 
619
  $response = $this->request( 'quick_config', $params );
620
 
621
  if ( $response->status === 200 ) {
622
  // @todo notify publish app
623
+ $params = [
624
  'AppID' => $app_exists->AppID
625
+ ];
626
 
627
  $response = $this->request( 'notify_app', $params );
628
 
630
  $response = true;
631
 
632
  // update app status
633
+ if ( $network )
634
+ update_site_option( 'cookie_notice_status', 'active' );
635
+ else
636
+ update_option( 'cookie_notice_status', 'active' );
637
  } else {
638
  // update app status
639
+ if ( $network )
640
+ update_site_option( 'cookie_notice_status', 'pending' );
641
+ else
642
+ update_option( 'cookie_notice_status', 'pending' );
643
 
644
  // errors?
645
+ if ( ! empty( $response->error ) )
646
  break;
 
647
 
648
  // errors?
649
  if ( ! empty( $response->message ) ) {
653
  }
654
  } else {
655
  // update app status
656
+ if ( $network )
657
+ update_site_option( 'cookie_notice_status', 'pending' );
658
+ else
659
+ update_option( 'cookie_notice_status', 'pending' );
660
 
661
  // errors?
662
  if ( ! empty( $response->error ) ) {
672
  }
673
 
674
  // all ok, return subscriptions
675
+ $response = (object) [];
676
  $response->subscriptions = $subscriptions;
 
677
  break;
678
 
679
  case 'configure':
680
+ $fields = [
681
  'cn_position',
682
  'cn_color_primary',
683
  'cn_color_background',
688
  'cn_laws',
689
  'cn_naming',
690
  'cn_privacy_paper',
691
+ 'cn_privacy_contact'
692
+ ];
693
 
694
+ $options = [];
695
 
696
  // loop through potential config form fields
697
  foreach ( $fields as $field ) {
698
+ switch ( $field ) {
699
  case 'cn_position':
700
  // sanitize position
701
  $position = isset( $_POST[$field] ) ? sanitize_key( $_POST[$field] ) : '';
702
 
703
  // valid position?
704
+ if ( in_array( $position, [ 'bottom', 'top', 'left', 'right', 'center' ], true ) )
705
  $options['design']['position'] = $position;
706
+ else
707
+ $options['design']['position'] = 'bottom';
708
  break;
709
 
710
  case 'cn_color_primary':
714
  // valid color?
715
  if ( empty( $color ) )
716
  $options['design']['primaryColor'] = '#20c19e';
717
+ else
718
+ $options['design']['primaryColor'] = $color;
719
  break;
720
 
721
  case 'cn_color_background':
725
  // valid color?
726
  if ( empty( $color ) )
727
  $options['design']['bannerColor'] = '#ffffff';
728
+ else
729
+ $options['design']['bannerColor'] = $color;
730
  break;
731
 
732
  case 'cn_color_border':
736
  // valid color?
737
  if ( empty( $color ) )
738
  $options['design']['borderColor'] = '#5e6a74';
739
+ else
740
+ $options['design']['borderColor'] = $color;
741
  break;
742
 
743
  case 'cn_color_text':
747
  // valid color?
748
  if ( empty( $color ) )
749
  $options['design']['textColor'] = '#434f58';
750
+ else
751
+ $options['design']['textColor'] = $color;
752
  break;
753
 
754
  case 'cn_color_heading':
758
  // valid color?
759
  if ( empty( $color ) )
760
  $options['design']['headingColor'] = '#434f58';
761
+ else
762
+ $options['design']['headingColor'] = $color;
763
  break;
764
 
765
  case 'cn_color_button_text':
769
  // valid color?
770
  if ( empty( $color ) )
771
  $options['design']['btnTextColor'] = '#ffffff';
772
+ else
773
+ $options['design']['btnTextColor'] = $color;
774
  break;
775
 
776
  case 'cn_laws':
777
+ $new_options = [];
778
 
779
  // any data?
780
+ if ( ! empty( $_POST[$field] ) && is_array( $_POST[$field] ) ) {
781
  $options['laws'] = array_map( 'sanitize_text_field', $_POST[$field] );
782
 
783
  foreach ( $options['laws'] as $law ) {
784
+ if ( in_array( $law, [ 'gdpr', 'ccpa' ], true ) )
785
  $new_options[$law] = true;
786
  }
787
  }
803
 
804
  case 'cn_naming':
805
  $naming = isset( $_POST[$field] ) ? (int) $_POST[$field] : 1;
806
+ $naming = in_array( $naming, [ 1, 2, 3 ] ) ? $naming : 1;
807
 
808
+ // english only for now
809
+ $level_names = [
810
+ 1 => [
811
  1 => 'Silver',
812
  2 => 'Gold',
813
  3 => 'Platinum'
814
+ ],
815
+ 2 => [
816
  1 => 'Private',
817
  2 => 'Balanced',
818
  3 => 'Personalized'
819
+ ],
820
+ 3 => [
821
  1 => 'Reject All',
822
  2 => 'Accept Some',
823
  3 => 'Accept All'
824
+ ]
825
+ ];
826
+
827
+ $options['text'] = [
828
+ 'levelNameText_1' => $level_names[$naming][1],
829
+ 'levelNameText_2' => $level_names[$naming][2],
830
+ 'levelNameText_3' => $level_names[$naming][3]
831
+ ];
 
832
  break;
833
 
834
  case 'cn_privacy_paper':
842
  }
843
 
844
  // set options
845
+ if ( $network )
846
+ set_site_transient( 'cookie_notice_app_config', $options, 24 * HOUR_IN_SECONDS );
847
+ else
848
+ set_transient( 'cookie_notice_app_config', $options, 24 * HOUR_IN_SECONDS );
849
  break;
850
 
851
  case 'select_plan':
859
  /**
860
  * API request.
861
  *
862
+ * @param string $request The requested action.
863
+ * @param array $params Parameters for the API action.
864
+ * @return string|array
865
  */
866
+ private function request( $request = '', $params = [] ) {
867
+ // get main instance
868
+ $cn = Cookie_Notice();
869
+
870
+ $api_args = [
871
+ 'timeout' => 60,
872
+ 'sslverify' => false,
873
+ 'headers' => [
874
+ 'x-api-key' => $cn->get_api_key()
875
+ ]
876
+ ];
877
+ $api_params = [];
878
  $json = false;
879
 
880
+ // check network
881
+ $network = $cn->is_network_admin();
882
+
883
  // get app token data
884
+ if ( $network )
885
+ $data_token = get_site_transient( 'cookie_notice_app_token' );
886
+ else
887
+ $data_token = get_transient( 'cookie_notice_app_token' );
888
+
889
  $api_token = ! empty( $data_token->token ) ? $data_token->token : '';
 
890
 
891
+ switch ( $request ) {
892
  case 'register':
893
+ $api_url = $cn->get_url( 'account_api', '/api/account/account/registration' );
894
  $api_args['method'] = 'POST';
895
  break;
896
 
897
  case 'login':
898
+ $api_url = $cn->get_url( 'account_api', '/api/account/account/login' );
899
  $api_args['method'] = 'POST';
900
  break;
901
 
902
  case 'list_apps':
903
+ $api_url = $cn->get_url( 'account_api', '/api/account/app/list' );
904
  $api_args['method'] = 'GET';
905
  $api_args['headers'] = array_merge(
906
+ $api_args['headers'],
907
+ [
908
+ 'Authorization' => 'Bearer ' . $api_token
909
+ ]
910
  );
911
  break;
912
 
913
  case 'app_create':
914
+ $api_url = $cn->get_url( 'account_api', '/api/account/app/add' );
915
  $api_args['method'] = 'POST';
916
  $api_args['headers'] = array_merge(
917
+ $api_args['headers'],
918
+ [
919
+ 'Authorization' => 'Bearer ' . $api_token
920
+ ]
921
  );
922
  break;
923
 
924
  case 'get_analytics':
925
+ $api_url = $cn->get_url( 'transactional_api', '/api/transactional/analytics/analytics-data' );
926
  $api_args['method'] = 'GET';
927
  $api_args['headers'] = array_merge(
928
+ $api_args['headers'],
929
+ [
930
+ 'app-id' => $cn->options['general']['app_id'],
931
+ 'app-secret-key' => $cn->options['general']['app_key']
932
+ ]
933
  );
934
  break;
935
 
936
  case 'get_config':
937
+ $api_url = $cn->get_url( 'designer_api', '/api/designer/user-design-live' );
938
  $api_args['method'] = 'GET';
939
  break;
940
 
941
  case 'quick_config':
942
  $json = true;
943
+ $api_url = $cn->get_url( 'designer_api', '/api/designer/user-design/quick' );
944
  $api_args['method'] = 'POST';
945
  $api_args['headers'] = array_merge(
946
+ $api_args['headers'],
947
+ [
948
+ 'Authorization' => 'Bearer ' . $api_token,
949
+ 'Content-Type' => 'application/json; charset=utf-8'
950
+ ]
951
  );
952
  break;
953
 
954
  case 'notify_app':
955
  $json = true;
956
+ $api_url = $cn->get_url( 'account_api', '/api/account/app/notifyAppPublished' );
957
  $api_args['method'] = 'POST';
958
  $api_args['headers'] = array_merge(
959
+ $api_args['headers'],
960
+ [
961
+ 'Authorization' => 'Bearer ' . $api_token,
962
+ 'Content-Type' => 'application/json; charset=utf-8'
963
+ ]
964
  );
965
  break;
966
 
967
  // braintree init token
968
  case 'get_token':
969
+ $api_url = $cn->get_url( 'account_api', '/api/account/braintree' );
970
  $api_args['method'] = 'GET';
971
  $api_args['headers'] = array_merge(
972
+ $api_args['headers'],
973
+ [
974
+ 'Authorization' => 'Bearer ' . $api_token
975
+ ]
976
  );
977
  break;
978
 
979
  // braintree get customer
980
  case 'get_customer':
981
  $json = true;
982
+ $api_url = $cn->get_url( 'account_api', '/api/account/braintree/findcustomer' );
983
  $api_args['method'] = 'POST';
984
  $api_args['data_format'] = 'body';
985
  $api_args['headers'] = array_merge(
986
+ $api_args['headers'],
987
+ [
988
+ 'Authorization' => 'Bearer ' . $api_token,
989
+ 'Content-Type' => 'application/json; charset=utf-8'
990
+ ]
991
  );
992
  break;
993
 
994
  // braintree create customer in vault
995
  case 'create_customer':
996
  $json = true;
997
+ $api_url = $cn->get_url( 'account_api', '/api/account/braintree/createcustomer' );
998
  $api_args['method'] = 'POST';
999
  $api_args['headers'] = array_merge(
1000
+ $api_args['headers'],
1001
+ [
1002
+ 'Authorization' => 'Bearer ' . $api_token,
1003
+ 'Content-Type' => 'application/json; charset=utf-8'
1004
+ ]
1005
  );
1006
  break;
1007
 
1008
  // braintree get subscriptions
1009
  case 'get_subscriptions':
1010
  $json = true;
1011
+ $api_url = $cn->get_url( 'account_api', '/api/account/braintree/subscriptionlists' );
1012
  $api_args['method'] = 'POST';
1013
  $api_args['headers'] = array_merge(
1014
+ $api_args['headers'],
1015
+ [
1016
+ 'Authorization' => 'Bearer ' . $api_token,
1017
+ 'Content-Type' => 'application/json; charset=utf-8'
1018
+ ]
1019
  );
1020
  break;
1021
 
1022
  // braintree create subscription
1023
  case 'create_subscription':
1024
  $json = true;
1025
+ $api_url = $cn->get_url( 'account_api', '/api/account/braintree/createsubscription' );
1026
  $api_args['method'] = 'POST';
1027
  $api_args['headers'] = array_merge(
1028
+ $api_args['headers'],
1029
+ [
1030
+ 'Authorization' => 'Bearer ' . $api_token,
1031
+ 'Content-Type' => 'application/json; charset=utf-8'
1032
+ ]
1033
  );
1034
  break;
1035
 
1036
  // braintree assign subscription
1037
  case 'assign_subscription':
1038
  $json = true;
1039
+ $api_url = $cn->get_url( 'account_api', '/api/account/braintree/assignsubscription' );
1040
  $api_args['method'] = 'POST';
1041
  $api_args['headers'] = array_merge(
1042
+ $api_args['headers'],
1043
+ [
1044
+ 'Authorization' => 'Bearer ' . $api_token,
1045
+ 'Content-Type' => 'application/json; charset=utf-8'
1046
+ ]
1047
  );
1048
  break;
1049
 
1050
+ // braintree create payment method
1051
  case 'create_payment_method':
1052
  $json = true;
1053
+ $api_url = $cn->get_url( 'account_api', '/api/account/braintree/createpaymentmethod' );
1054
  $api_args['method'] = 'POST';
1055
  $api_args['headers'] = array_merge(
1056
+ $api_args['headers'],
1057
+ [
1058
+ 'Authorization' => 'Bearer ' . $api_token,
1059
+ 'Content-Type' => 'application/json; charset=utf-8'
1060
+ ]
1061
  );
1062
  break;
1063
  }
1066
  foreach ( $params as $key => $param ) {
1067
  if ( is_object( $param ) )
1068
  $api_params[$key] = $param;
1069
+ elseif ( is_array( $param ) )
1070
+ $api_params[$key] = array_map( 'sanitize_text_field', $param );
1071
  else
1072
  $api_params[$key] = sanitize_text_field( $param );
1073
  }
1081
  $response = wp_remote_request( $api_url, $api_args );
1082
 
1083
  if ( is_wp_error( $response ) )
1084
+ $result = [ 'error' => $response->get_error_message() ];
1085
  else {
1086
  $content_type = wp_remote_retrieve_header( $response, 'Content-Type' );
1087
 
1088
+ // html response, means error
1089
+ if ( $content_type == 'text/html' )
1090
+ $result = [ 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
1091
+ else {
1092
  $result = wp_remote_retrieve_body( $response );
1093
+
1094
  // detect json or array
1095
  $result = is_array( $result ) ? $result : json_decode( $result );
1096
  }
1106
  */
1107
  public function check_cron() {
1108
  // compliance acitve only
1109
+ if ( Cookie_Notice()->get_status() === 'active' ) {
1110
  if ( ! wp_next_scheduled( 'cookie_notice_get_app_analytics' ) ) {
1111
  // set schedule
1112
  wp_schedule_event( time(), 'hourly', 'cookie_notice_get_app_analytics' ); // hourly
1113
  }
1114
+ } elseif ( wp_next_scheduled( 'cookie_notice_get_app_analytics' ) )
1115
  wp_clear_scheduled_hook( 'cookie_notice_get_app_analytics' );
 
1116
  }
1117
 
1118
  /**
1119
+ * Get app config.
1120
+ *
1121
+ * @return array
1122
  */
1123
+ public function get_app_analytics( $force_update = false ) {
1124
+ // get main instance
1125
+ $cn = Cookie_Notice();
1126
 
1127
+ $result = [];
1128
+ $allow_one_cron_per_hour = false;
1129
+
1130
+ if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
1131
+ $app_id = $cn->network_options['app_id'];
1132
+ $network = true;
1133
+ $allow_one_cron_per_hour = true;
1134
+ } else {
1135
+ $app_id = $cn->options['general']['app_id'];
1136
+ $network = false;
1137
+ }
1138
+
1139
+ // in global override mode allow only one cron per hour
1140
+ if ( $allow_one_cron_per_hour && ! $force_update ) {
1141
+ $analytics = get_site_option( 'cookie_notice_app_analytics', [] );
1142
+
1143
+ // analytics data?
1144
+ if ( ! empty( $analytics ) ) {
1145
+ $updated = strtotime( $analytics['lastUpdated'] );
1146
+
1147
+ // last updated less than an hour?
1148
+ if ( $updated !== false && current_time( 'timestamp', true ) - $updated < 3600 )
1149
+ return;
1150
+ }
1151
+ }
1152
 
1153
+ $response = $this->request(
1154
+ 'get_analytics',
1155
+ [
1156
+ 'AppID' => $app_id
1157
+ ]
1158
+ );
1159
 
 
1160
  // get analytics
1161
  if ( ! empty( $response->data ) ) {
1162
+ $result = ! empty( $response->data ) ? map_deep( (array) $response->data, 'sanitize_text_field' ) : [];
1163
 
1164
  // update app status
1165
  if ( ! empty( $result ) ) {
1166
  // add time updated
1167
  $result['lastUpdated'] = date( 'Y-m-d H:i:s', current_time( 'timestamp', true ) );
1168
 
1169
+ if ( $network )
1170
+ update_site_option( 'cookie_notice_app_analytics', $result );
1171
+ else
1172
+ update_option( 'cookie_notice_app_analytics', $result, false );
1173
  }
1174
  }
 
 
1175
  }
1176
 
1177
  /**
1178
+ * Get app status.
1179
+ *
1180
+ * @return bool|string
1181
  */
1182
  public function get_app_status( $app_id ) {
1183
  $result = '';
1185
  if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1186
  return false;
1187
 
1188
+ $response = $this->request(
1189
+ 'get_config',
1190
+ [
1191
+ 'AppID' => $app_id
1192
+ ]
1193
  );
1194
 
1195
+ if ( ! empty( $response->data ) )
 
 
1196
  $result = 'active';
1197
+ else {
1198
  if ( ! empty( $response->error ) ) {
1199
+ if ( $response->error == 'App is not published yet' )
1200
  $result = 'pending';
1201
  else
1202
  $result = '';
1210
  * Defines the function used to initial the cURL library.
1211
  *
1212
  * @param string $url To URL to which the request is being made
1213
+ * @param string $args The URL query parameters
1214
+ * @return string|bool|null
1215
  */
1216
  private function curl( $url, $args ) {
1217
  $curl = curl_init( $url );
1218
 
1219
+ $headers = [];
1220
 
1221
  foreach ( $args['headers'] as $header => $value ) {
1222
  $headers[] = $header . ': ' . $value;
1240
 
1241
  return $response;
1242
  }
1243
+ }
 
includes/welcome-frontend.php CHANGED
@@ -1,132 +1,132 @@
1
- <?php
2
- // exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) )
4
- exit;
5
-
6
- /**
7
- * Cookie_Notice_Welcome_Frontend class.
8
- *
9
- * @class Cookie_Notice_Welcome_Frontend
10
- */
11
- class Cookie_Notice_Welcome_Frontend {
12
- private $widget_url = '';
13
- private $preview_mode = false;
14
-
15
- /**
16
- * Constructor.
17
- *
18
- * @return void
19
- */
20
- public function __construct() {
21
- add_action( 'after_setup_theme', array( $this, 'preview_init' ), 1 );
22
-
23
- $this->widget_url = '//cdn.hu-manity.co/hu-banner.min.js';
24
- }
25
-
26
- /**
27
- * Initialize preview mode.
28
- */
29
- public function preview_init() {
30
- // check preview mode
31
- $this->preview_mode = isset( $_GET['cn_preview_mode'] ) ? absint( $_GET['cn_preview_mode'] ) : false;
32
-
33
- if ( $this->preview_mode !== false ) {
34
- // filters
35
- add_filter( 'show_admin_bar', '__return_false' );
36
- add_filter( 'cn_cookie_notice_output', '__return_false', 1000 );
37
-
38
- // actions
39
- add_action( 'wp_enqueue_scripts', array( $this, 'wp_dequeue_scripts' ) );
40
-
41
- // only in live preview
42
- if ( $this->preview_mode === 1 ) {
43
- add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );
44
- add_action( 'wp_head', array( $this, 'wp_head_scripts' ), 0 );
45
- }
46
- }
47
- }
48
-
49
- /**
50
- * Load scripts and styles.
51
- *
52
- * @return void
53
- */
54
- public function wp_enqueue_scripts( $page ) {
55
- // show only in live preview
56
- if ( $this->preview_mode === 1 ) {
57
- wp_enqueue_script( 'cookie-notice-welcome-frontend', plugins_url( '../js/front-welcome.js', __FILE__ ), array( 'jquery', 'underscore' ), Cookie_Notice()->defaults['version'] );
58
-
59
- wp_localize_script(
60
- 'cookie-notice-welcome-frontend',
61
- 'cnFrontWelcome',
62
- array(
63
- 'previewMode' => $this->preview_mode,
64
- 'allowedURLs' => $this->get_allowed_urls(),
65
- 'levelNames' => Cookie_Notice()->settings->level_names,
66
- 'textStrings' => Cookie_Notice()->settings->text_strings
67
- )
68
- );
69
- }
70
- }
71
-
72
- /**
73
- * Unload scripts and styles.
74
- *
75
- * @return void
76
- */
77
- public function wp_dequeue_scripts( $page ) {
78
- // deregister native CN
79
- wp_dequeue_script( 'cookie-notice-front' );
80
- }
81
-
82
- /**
83
- * .
84
- *
85
- * @return void
86
- */
87
- public function wp_head_scripts() {
88
- $options = array(
89
- 'currentLanguage' => 'en',
90
- 'previewMode' => true,
91
- 'debugMode' => true,
92
- 'config' => array(
93
- 'privacyPaper' => true,
94
- 'privacyContact' => true
95
- )
96
- );
97
-
98
- echo '
99
- <!-- Hu Banner -->
100
- <script type="text/javascript">
101
- var huOptions = ' . json_encode( $options ) . ';
102
- </script>
103
- <script type="text/javascript" src="' . $this->widget_url . '"></script>
104
- <style>.hu-preview-mode #hu::after {content: "";position: fixed;width: 100%;height: 100%;display: block;top: 0;left: 0;}</style>';
105
- }
106
-
107
- /**
108
- * Get URLs allowed to be previewed.
109
- *
110
- * @return array
111
- */
112
- public function get_allowed_urls() {
113
- $allowed_urls = array( home_url( '/' ) );
114
-
115
- if ( is_ssl() && ! $this->is_cross_domain() )
116
- $allowed_urls[] = home_url( '/', 'https' );
117
-
118
- return $allowed_urls;
119
- }
120
-
121
- /**
122
- * Determines whether the admin and the frontend are on different domains.
123
- *
124
- * @return bool
125
- */
126
- public function is_cross_domain() {
127
- $admin_origin = wp_parse_url( admin_url() );
128
- $home_origin = wp_parse_url( home_url() );
129
-
130
- return ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
131
- }
132
  }
1
+ <?php
2
+ // exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) )
4
+ exit;
5
+
6
+ /**
7
+ * Cookie_Notice_Welcome_Frontend class.
8
+ *
9
+ * @class Cookie_Notice_Welcome_Frontend
10
+ */
11
+ class Cookie_Notice_Welcome_Frontend {
12
+
13
+ private $preview_mode = false;
14
+
15
+ /**
16
+ * Constructor.
17
+ *
18
+ * @return void
19
+ */
20
+ public function __construct() {
21
+ add_action( 'after_setup_theme', array( $this, 'preview_init' ), 1 );
22
+ }
23
+
24
+ /**
25
+ * Initialize preview mode.
26
+ *
27
+ * @return void
28
+ */
29
+ public function preview_init() {
30
+ // check preview mode
31
+ $this->preview_mode = isset( $_GET['cn_preview_mode'] ) ? absint( $_GET['cn_preview_mode'] ) : false;
32
+
33
+ if ( $this->preview_mode !== false ) {
34
+ // filters
35
+ add_filter( 'show_admin_bar', '__return_false' );
36
+ add_filter( 'cn_cookie_notice_output', '__return_false', 1000 );
37
+
38
+ // actions
39
+ add_action( 'wp_enqueue_scripts', array( $this, 'wp_dequeue_scripts' ) );
40
+
41
+ // only in live preview
42
+ if ( $this->preview_mode === 1 ) {
43
+ add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );
44
+ add_action( 'wp_head', array( $this, 'wp_head_scripts' ), 0 );
45
+ }
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Load scripts and styles.
51
+ *
52
+ * @return void
53
+ */
54
+ public function wp_enqueue_scripts() {
55
+ // show only in live preview
56
+ if ( $this->preview_mode === 1 ) {
57
+ wp_enqueue_script( 'cookie-notice-welcome-frontend', plugins_url( '../js/front-welcome.js', __FILE__ ), array( 'jquery', 'underscore' ), Cookie_Notice()->defaults['version'] );
58
+
59
+ wp_localize_script(
60
+ 'cookie-notice-welcome-frontend',
61
+ 'cnFrontWelcome',
62
+ array(
63
+ 'previewMode' => $this->preview_mode,
64
+ 'allowedURLs' => $this->get_allowed_urls(),
65
+ 'levelNames' => Cookie_Notice()->settings->level_names,
66
+ 'textStrings' => Cookie_Notice()->settings->text_strings
67
+ )
68
+ );
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Unload scripts and styles.
74
+ *
75
+ * @return void
76
+ */
77
+ public function wp_dequeue_scripts() {
78
+ // deregister native cookie notice script
79
+ wp_dequeue_script( 'cookie-notice-front' );
80
+ }
81
+
82
+ /**
83
+ * Load cookie compliance script.
84
+ *
85
+ * @return void
86
+ */
87
+ public function wp_head_scripts() {
88
+ $options = array(
89
+ 'currentLanguage' => 'en',
90
+ 'previewMode' => true,
91
+ 'debugMode' => true,
92
+ 'config' => array(
93
+ 'privacyPaper' => true,
94
+ 'privacyContact' => true
95
+ )
96
+ );
97
+
98
+ echo '
99
+ <!-- Hu Banner -->
100
+ <script type="text/javascript">
101
+ var huOptions = ' . json_encode( $options ) . ';
102
+ </script>
103
+ <script type="text/javascript" src="' . Cookie_Notice()->get_url( 'widget' ) . '"></script>
104
+ <style>.hu-preview-mode #hu::after {content: "";position: fixed;width: 100%;height: 100%;display: block;top: 0;left: 0;}</style>';
105
+ }
106
+
107
+ /**
108
+ * Get URLs allowed to be previewed.
109
+ *
110
+ * @return array
111
+ */
112
+ public function get_allowed_urls() {
113
+ $allowed_urls = array( home_url( '/' ) );
114
+
115
+ if ( is_ssl() && ! $this->is_cross_domain() )
116
+ $allowed_urls[] = home_url( '/', 'https' );
117
+
118
+ return $allowed_urls;
119
+ }
120
+
121
+ /**
122
+ * Determines whether the admin and the frontend are on different domains.
123
+ *
124
+ * @return bool
125
+ */
126
+ public function is_cross_domain() {
127
+ $admin_origin = wp_parse_url( admin_url() );
128
+ $home_origin = wp_parse_url( home_url() );
129
+
130
+ return ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
131
+ }
132
  }
includes/welcome.php CHANGED
@@ -5,84 +5,100 @@ if ( ! defined( 'ABSPATH' ) )
5
 
6
  /**
7
  * Cookie_Notice_Welcome class.
8
- *
9
  * @class Cookie_Notice_Welcome
10
  */
11
  class Cookie_Notice_Welcome {
12
-
13
- private $app_login_url = 'https://app.hu-manity.co/#/en/cc2/login';
14
-
15
- private $pricing_monthly = array();
16
- private $pricing_yearly = array();
17
 
 
 
 
 
 
 
 
 
18
  public function __construct() {
19
  // actions
20
- add_action( 'admin_init', array( $this, 'init' ) );
21
- add_action( 'admin_init', array( $this, 'welcome' ) );
22
- add_action( 'wp_ajax_cn_welcome_screen', array( $this, 'welcome_screen' ) );
23
  }
24
-
25
  /**
26
- * Init.
 
 
27
  */
28
  public function init() {
29
- $this->pricing_monthly = array(
30
- 'compliance_monthly_notrial' => '14.95',
31
- 'compliance_monthly_5' => '29.95',
32
- 'compliance_monthly_10' => '49.95',
33
- 'compliance_monthly_20' => '69.95'
34
- );
35
-
36
- $this->pricing_yearly = array(
37
- 'compliance_yearly_notrial' => '149.50',
38
- 'compliance_yearly_5' => '299.50',
39
- 'compliance_yearly_10' => '499.50',
40
- 'compliance_yearly_20' => '699.50'
41
- );
42
  }
43
 
44
  /**
45
  * Load scripts and styles - admin.
 
 
46
  */
47
- public function admin_enqueue_scripts( $page ) {
48
- if ( in_array( Cookie_Notice()->get_status(), array( 'active', 'pending' ) ) )
 
 
 
49
  return;
50
-
51
  wp_enqueue_style( 'dashicons' );
52
-
53
- wp_enqueue_style( 'cookie-notice-modaal', plugins_url( '../assets/modaal/css/modaal.min.css', __FILE__ ), array(), Cookie_Notice()->defaults['version'] );
54
- wp_enqueue_script( 'cookie-notice-modaal', plugins_url( '../assets/modaal/js/modaal.min.js', __FILE__ ), array(), Cookie_Notice()->defaults['version'] );
55
-
56
- wp_enqueue_style( 'cookie-notice-spectrum', plugins_url( '../assets/spectrum/spectrum.min.css', __FILE__ ), array(), Cookie_Notice()->defaults['version'] );
57
-
58
- wp_enqueue_style( 'cookie-notice-microtip', plugins_url( '../assets/microtip/microtip.min.css', __FILE__ ), array(), Cookie_Notice()->defaults['version'] );
59
-
60
- wp_enqueue_script( 'cookie-notice-spectrum', plugins_url( '../assets/spectrum/spectrum.min.js', __FILE__ ), array(), Cookie_Notice()->defaults['version'] );
61
- wp_enqueue_script( 'cookie-notice-welcome', plugins_url( '../js/admin-welcome.js', __FILE__ ), array( 'jquery', 'jquery-ui-core', 'jquery-ui-progressbar' ), Cookie_Notice()->defaults['version'] );
62
- wp_enqueue_script( 'cookie-notice-braintree-client', 'https://js.braintreegateway.com/web/3.71.0/js/client.min.js', array(), null, false );
63
- wp_enqueue_script( 'cookie-notice-braintree-hostedfields', 'https://js.braintreegateway.com/web/3.71.0/js/hosted-fields.min.js', array(), null, false );
64
- wp_enqueue_script( 'cookie-notice-braintree-paypal', 'https://js.braintreegateway.com/web/3.71.0/js/paypal-checkout.min.js', array(), null, false );
65
-
 
 
66
  $js_args = array(
67
- 'ajaxURL' => admin_url( 'admin-ajax.php' ),
68
- 'nonce' => wp_create_nonce( 'cookie-notice-welcome' ),
69
- 'initModal' => get_transient( 'cn_show_welcome' ), // welcome modal
70
- 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ),
71
- 'statusPassed' => __( 'Passed', 'cookie-notice' ),
72
- 'statusFailed' => __( 'Failed', 'cookie-notice' ),
73
- 'paidMonth' => __( 'monthly', 'cookie-notice' ),
74
- 'paidYear' => __( 'yearly', 'cookie-notice' ),
75
- 'pricingMonthly' => $this->pricing_monthly,
76
- 'pricingYearly' => $this->pricing_yearly,
77
- 'complianceStatus' => Cookie_Notice()->get_status(),
78
- 'complianceFailed' => __( '<em>Compliance Failed!</em>Your website does not achieve minimum viable compliance. <b><a href="#" class="cn-sign-up">Sign up to Cookie Compliance</a></b> to bring your site into compliance with the latest data privacy rules and regulations.', 'cookie-notice' ),
79
- 'compliancePassed' => __( '<em>Compliance Passed!</em>Congratulations. Your website meets minimum viable compliance.', 'cookie-notice' ),
80
- 'licensesAvailable' => __( 'available', 'cookie-notice' ),
81
- 'invalidFields' => __( 'Please fill all the required fields.', 'cookie-notice' )
 
82
  );
83
-
84
  // delete the show modal transient
85
- delete_transient( 'cn_show_welcome' );
 
 
 
86
 
87
  wp_localize_script(
88
  'cookie-notice-welcome',
@@ -92,7 +108,7 @@ class Cookie_Notice_Welcome {
92
 
93
  wp_enqueue_style( 'cookie-notice-welcome', plugins_url( '../css/admin-welcome.css', __FILE__ ) );
94
  }
95
-
96
  /**
97
  * Add one or more classes to the body tag in the dashboard.
98
  *
@@ -101,44 +117,48 @@ class Cookie_Notice_Welcome {
101
  */
102
  public function admin_body_class( $classes ) {
103
  $classes .= ' folded';
104
-
105
  return $classes;
106
  }
107
 
108
  /**
109
  * Send user to the welcome page on first activation.
110
  *
 
 
111
  * @return void
112
  */
113
  public function welcome() {
114
  global $pagenow;
115
-
116
  if ( $pagenow != 'admin.php' )
117
  return;
118
-
119
  if ( isset( $_GET['page'] ) && $_GET['page'] !== 'cookie-notice' )
120
  return;
121
 
122
- // bail if activating from network, or bulk, or within an iFrame
123
- if ( is_network_admin() || isset( $_GET['activate-multi'] ) || defined( 'IFRAME_REQUEST' ) )
124
  return;
125
 
126
- if ( (isset( $_GET['action'] ) && 'upgrade-plugin' == $_GET['action']) && (isset( $_GET['plugin'] ) && strstr( $_GET['plugin'], 'cookie-notice.php' )) )
127
  return;
128
 
129
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
130
  add_action( 'admin_footer', array( $this, 'admin_footer' ) );
131
-
132
  // add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
133
  }
134
-
135
  /**
136
  * Welcome modal container.
 
 
137
  */
138
  public function admin_footer() {
139
  echo '<button id="cn-modal-trigger" style="display:none;"></button>';
140
  }
141
-
142
  /**
143
  * Output the welcome screen.
144
  *
@@ -151,34 +171,31 @@ class Cookie_Notice_Welcome {
151
 
152
  $this->welcome_screen( $screen );
153
  }
154
-
155
  /**
156
  * Render welcome screen sidebar step.
157
- *
158
- * @param int $step
159
- * @return mixed
 
160
  */
161
  public function welcome_screen( $screen, $echo = true ) {
162
- global $current_user;
163
-
164
  if ( ! current_user_can( 'install_plugins' ) )
165
  wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
166
 
167
  $sidebars = array( 'about', 'login', 'register', 'configure', 'select_plan', 'success' );
168
  $steps = array( 1, 2, 3, 4 );
169
  $screens = array_merge( $sidebars, $steps );
170
-
171
- $is_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
172
  $screen = ! empty( $screen ) && in_array( $screen, $screens ) ? $screen : ( isset( $_REQUEST['screen'] ) && in_array( $_REQUEST['screen'], $screens ) ? $_REQUEST['screen'] : '' );
173
 
174
  if ( empty( $screen ) )
175
  wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
176
 
177
- if ( $is_ajax && ! check_ajax_referer( 'cookie-notice-welcome', 'nonce' ) )
178
  wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
179
 
180
  // get token data
181
- $token_data = get_transient( 'cookie_notice_app_token' );
182
 
183
  // step screens
184
  if ( in_array( $screen, $steps ) ) {
@@ -187,7 +204,7 @@ class Cookie_Notice_Welcome {
187
 
188
  if ( $screen == 1 ) {
189
  $html .= $this->welcome_screen( 'about', false );
190
-
191
  $html .= '
192
  <div class="cn-content cn-sidebar-visible">
193
  <div class="cn-inner">
@@ -210,12 +227,11 @@ class Cookie_Notice_Welcome {
210
  <button type="button" class="cn-btn cn-btn-lg cn-btn-transparent cn-skip-button">' . __( 'Skip for now', 'cookie-notice' ) . '</button>
211
  </div>
212
  ';
213
-
214
  $html .= '
215
  </div>
216
  </div>
217
  </div>';
218
-
219
  } elseif ( $screen == 2 ) {
220
  $html .= $this->welcome_screen( 'configure', false );
221
 
@@ -225,10 +241,10 @@ class Cookie_Notice_Welcome {
225
  </div>';
226
  } elseif ( $screen == 3 ) {
227
  // get options
228
- $app_config = get_transient( 'cookie_notice_app_config' );
229
 
230
  $html .= $this->welcome_screen( 'register', false );
231
-
232
  $html .= '
233
  <div class="cn-content cn-sidebar-visible">
234
  <div class="cn-inner">
@@ -242,7 +258,7 @@ class Cookie_Notice_Welcome {
242
  <div class="cn-billing-wrapper cn-radio-wrapper">
243
  <label for="cn_billing_monthly"><input id="cn_billing_monthly" type="radio" name="cn_billing" value="monthly" checked><span><span>' . __( 'Billing Monthly', 'cookie-notice' ) . '</span><span class="cn-plan-overlay"></span></span></label><label for="cn_billing_yearly"><input id="cn_billing_yearly" type="radio" name="cn_billing" value="yearly"><span><span>' . __( 'Billing Yearly', 'cookie-notice' ) . '</span> <span class="cn-price-off">(' . __( '15% off', 'cookie-notice' ) . ')</span><span class="cn-plan-overlay"></span></span></label>
244
  </div>
245
-
246
  $html .= '
247
  <div class="cn-hero-image">
248
  <div class="cn-flex-item">
@@ -279,7 +295,7 @@ class Cookie_Notice_Welcome {
279
  </div>';
280
  */
281
 
282
- $html .= '
283
  <h3 class="cn-pricing-select">' . __( 'Compliance Plans', 'cookie-notice' ) . ':</h3>
284
  <div class="cn-pricing-type cn-radio-wrapper">
285
  <div>
@@ -301,7 +317,7 @@ class Cookie_Notice_Welcome {
301
  <p class="cn-included"><span class="cn-icon"></span>' . __( 'GDPR, CCPA, ePrivacy, PECR compliance', 'cookie-notice' ) . '</p>
302
  <p class="cn-included"><span class="cn-icon"></span>' . __( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
303
  <p class="cn-excluded"><span class="cn-icon"></span>' . __( '<b>1,000</b> visits / month', 'cookie-notice' ) . '</p>
304
- <p class="cn-excluded"><span class="cn-icon"></span>' . __( '<b>30 days</b> consent storage', 'cookie-notice' ) . '</p>
305
  <p class="cn-excluded"><span class="cn-icon"></span>' . __( '<b>1 additional</b> language', 'cookie-notice' ) . '</p>
306
  <p class="cn-excluded"><span class="cn-icon"></span>' . __( '<b>Basic</b> Support', 'cookie-notice' ) . '</p>
307
  </div>
@@ -330,7 +346,7 @@ class Cookie_Notice_Welcome {
330
  <p class="cn-included"><span class="cn-icon"></span>' . __( 'GDPR, CCPA, ePrivacy, PECR compliance', 'cookie-notice' ) . '</p>
331
  <p class="cn-included"><span class="cn-icon"></span>' . __( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
332
  <p class="cn-included"><span class="cn-icon"></span>' . __( '<b>Unlimited</b> visits', 'cookie-notice' ) . '</p>
333
- <p class="cn-included"><span class="cn-icon"></span>' . __( '<b>Lifetime</b> consent storage', 'cookie-notice' ) . '</p>
334
  <p class="cn-included"><span class="cn-icon"></span>' . __( '<b>Unlimited</b> languages', 'cookie-notice' ) . '</p>
335
  <p class="cn-included"><span class="cn-icon"></span>' . __( '<b>Premium</b> Support', 'cookie-notice' ) . '</p>
336
  </div>
@@ -343,16 +359,14 @@ class Cookie_Notice_Welcome {
343
  <div class="cn-buttons">
344
  <button type="button" class="cn-btn cn-btn-lg cn-btn-transparent cn-skip-button">' . __( "I don’t want to create an account now", 'cookie-notice' ) . '</button>
345
  </div>';
346
-
347
-
348
  $html .= '
349
  </div>
350
  </div>
351
  </div>';
352
-
353
  } elseif ( $screen == 4 ) {
354
  $html .= $this->welcome_screen( 'success', false );
355
-
356
  $html .= '
357
  <div class="cn-content cn-sidebar-visible">
358
  <div class="cn-inner">
@@ -363,7 +377,7 @@ class Cookie_Notice_Welcome {
363
  <p>' . __( 'Log in to your Cookie Compliance&trade; account and continue configuring your Privacy Experience.', 'cookie-notice' ) . '</p>
364
  </div>
365
  <div class="cn-buttons">
366
- <a href="' . $this->app_login_url . '" class="cn-btn cn-btn-lg" target="_blank">' . __( 'Go to Application', 'cookie-notice' ) . '</a>
367
  </div>
368
  </div>
369
  </div>
@@ -385,7 +399,7 @@ class Cookie_Notice_Welcome {
385
  <div class="cn-header">
386
  <div class="cn-top-bar">
387
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
388
- </div>
389
  </div>
390
  <div class="cn-body">
391
  <h2>' . __( 'Compliance check', 'cookie-notice' ) . '</h2>
@@ -414,7 +428,7 @@ class Cookie_Notice_Welcome {
414
  <div class="cn-header">
415
  <div class="cn-top-bar">
416
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
417
- </div>
418
  </div>
419
  <div class="cn-body">
420
  <h2>' . __( 'Live Setup', 'cookie-notice' ) . '</h2>
@@ -512,7 +526,7 @@ class Cookie_Notice_Welcome {
512
  <div class="cn-header">
513
  <div class="cn-top-bar">
514
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
515
- </div>
516
  </div>
517
  <div class="cn-body">
518
  <h2>' . __( 'Compliance account', 'cookie-notice' ) . '</h2>
@@ -610,9 +624,7 @@ class Cookie_Notice_Welcome {
610
 
611
  $html .= '
612
  </form>
613
- </div>';
614
-
615
- $html .= '
616
  </div>
617
  </div>';
618
  } elseif ( $screen === 'login' ) {
@@ -622,7 +634,7 @@ class Cookie_Notice_Welcome {
622
  <div class="cn-header">
623
  <div class="cn-top-bar">
624
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
625
- </div>
626
  </div>
627
  <div class="cn-body">
628
  <h2>' . __( 'Compliance Sign in', 'cookie-notice' ) . '</h2>
@@ -644,7 +656,7 @@ class Cookie_Notice_Welcome {
644
  <div class="cn-field cn-field-submit cn-nav">
645
  <button type="submit" class="cn-btn cn-screen-button" tabindex="4" ' . /* data-screen="4" */ '><span class="cn-spinner"></span>' . __( 'Sign in', 'cookie-notice' ) . '</button>
646
  </div>';
647
-
648
  // get site language
649
  $locale = get_locale();
650
  $locale_code = explode( '_', $locale );
@@ -658,9 +670,7 @@ class Cookie_Notice_Welcome {
658
  </form>
659
  <p>' . __( 'Don\'t have an account yet?', 'cookie-notice' ) . ' <a href="#" class="cn-screen-button" data-screen="register">' . __( 'Sign up', 'cookie-notice' ) . '</a></p>
660
  </div>
661
- </div>';
662
-
663
- $html .= '
664
  <div id="cn-accordion-billing" class="cn-accordion-item cn-form-container cn-collapsed cn-disabled" tabindex="-1">
665
  <div class="cn-accordion-header cn-form-header">
666
  <button class="cn-accordion-button" type="button">2. ' . __( 'Select Plan', 'cookie-notice' ) . '</button>
@@ -680,7 +690,7 @@ class Cookie_Notice_Welcome {
680
  <div class="cn-field cn-fieldset" id="cn_submit_free">
681
  <button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . __( 'Confirm', 'cookie-notice' ) . '</button>
682
  </div>
683
-
684
  <div class="cn-field cn-fieldset cn-hidden" id="cn_submit_pro">
685
  <input type="hidden" name="cn_payment_identifier" value="" />
686
  <div class="cn-field cn-field-radio">
@@ -712,7 +722,7 @@ class Cookie_Notice_Welcome {
712
  <div id="cn_paypal_button"></div>
713
  </div>
714
  </div>
715
-
716
  <div class="cn-field cn-fieldset cn-hidden" id="cn_submit_license">
717
  <div class="cn-field cn-field-select" id="cn-subscriptions-list">
718
  <label for="cn-subscription-select">' . __( 'Select subscription', 'cookie-notice' ) . '​</label>
@@ -736,15 +746,14 @@ class Cookie_Notice_Welcome {
736
  <div class="cn-header">
737
  <div class="cn-top-bar">
738
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
739
- </div>
740
  </div>
741
  <div class="cn-body">
742
  <h2>' . __( 'Success!', 'cookie-notice' ) . '</h2>
743
- <div class="cn-lead"><p><b>' . __( 'You have successfully upgraded your website to Cookie Compliance&trade;', 'cookie-notice' ) . '</b></p><p>' . sprintf( __( 'Go to Cookie Compliance&trade; application now. Or access it anytime from your <a href="%s">Cookie Notice settings page</a>.', 'cookie-notice' ), esc_url( admin_url( 'admin.php?page=cookie-notice' ) ) ) . '</p></div>
744
  </div>';
745
  }
746
 
747
-
748
  $html .= '
749
  <div class="cn-footer">';
750
  /*
@@ -764,7 +773,6 @@ class Cookie_Notice_Welcome {
764
  </div>
765
  </div>
766
  </div>';
767
-
768
  }
769
 
770
  if ( $echo )
@@ -772,7 +780,7 @@ class Cookie_Notice_Welcome {
772
  else
773
  return $html;
774
 
775
- if ( $is_ajax )
776
  exit();
777
  }
778
  }
5
 
6
  /**
7
  * Cookie_Notice_Welcome class.
8
+ *
9
  * @class Cookie_Notice_Welcome
10
  */
11
  class Cookie_Notice_Welcome {
 
 
 
 
 
12
 
13
+ private $pricing_monthly = [];
14
+ private $pricing_yearly = [];
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @return void
20
+ */
21
  public function __construct() {
22
  // actions
23
+ add_action( 'admin_init', [ $this, 'init' ] );
24
+ add_action( 'admin_init', [ $this, 'welcome' ] );
25
+ add_action( 'wp_ajax_cn_welcome_screen', [ $this, 'welcome_screen' ] );
26
  }
27
+
28
  /**
29
+ * Load defaults.
30
+ *
31
+ * @return void
32
  */
33
  public function init() {
34
+ $this->pricing_monthly = [
35
+ 'compliance_monthly_notrial' => '14.95',
36
+ 'compliance_monthly_5' => '29.95',
37
+ 'compliance_monthly_10' => '49.95',
38
+ 'compliance_monthly_20' => '69.95'
39
+ ];
40
+
41
+ $this->pricing_yearly = [
42
+ 'compliance_yearly_notrial' => '149.50',
43
+ 'compliance_yearly_5' => '299.50',
44
+ 'compliance_yearly_10' => '499.50',
45
+ 'compliance_yearly_20' => '699.50'
46
+ ];
47
  }
48
 
49
  /**
50
  * Load scripts and styles - admin.
51
+ *
52
+ * @return void
53
  */
54
+ public function admin_enqueue_scripts( $page ) {
55
+ // get main instance
56
+ $cn = Cookie_Notice();
57
+
58
+ if ( $cn->check_status( $cn->get_status() ) )
59
  return;
60
+
61
  wp_enqueue_style( 'dashicons' );
62
+
63
+ wp_enqueue_style( 'cookie-notice-modaal', plugins_url( '../assets/modaal/css/modaal.min.css', __FILE__ ), [], $cn->defaults['version'] );
64
+ wp_enqueue_script( 'cookie-notice-modaal', plugins_url( '../assets/modaal/js/modaal.min.js', __FILE__ ), [], $cn->defaults['version'] );
65
+
66
+ wp_enqueue_style( 'cookie-notice-spectrum', plugins_url( '../assets/spectrum/spectrum.min.css', __FILE__ ), [], $cn->defaults['version'] );
67
+ wp_enqueue_style( 'cookie-notice-microtip', plugins_url( '../assets/microtip/microtip.min.css', __FILE__ ), [], $cn->defaults['version'] );
68
+
69
+ wp_enqueue_script( 'cookie-notice-spectrum', plugins_url( '../assets/spectrum/spectrum.min.js', __FILE__ ), [], $cn->defaults['version'] );
70
+ wp_enqueue_script( 'cookie-notice-welcome', plugins_url( '../js/admin-welcome.js', __FILE__ ), array( 'jquery', 'jquery-ui-core', 'jquery-ui-progressbar' ), $cn->defaults['version'] );
71
+ wp_enqueue_script( 'cookie-notice-braintree-client', 'https://js.braintreegateway.com/web/3.71.0/js/client.min.js', [], null, false );
72
+ wp_enqueue_script( 'cookie-notice-braintree-hostedfields', 'https://js.braintreegateway.com/web/3.71.0/js/hosted-fields.min.js', [], null, false );
73
+ wp_enqueue_script( 'cookie-notice-braintree-paypal', 'https://js.braintreegateway.com/web/3.71.0/js/paypal-checkout.min.js', [], null, false );
74
+
75
+ // check network
76
+ $network = $cn->is_network_admin();
77
+
78
  $js_args = array(
79
+ 'ajaxURL' => admin_url( 'admin-ajax.php' ),
80
+ 'network' => (int) $network,
81
+ 'nonce' => wp_create_nonce( 'cookie-notice-welcome' ),
82
+ 'initModal' => $network ? get_site_transient( 'cn_show_welcome' ) : get_transient( 'cn_show_welcome' ), // welcome modal
83
+ 'error' => __( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ),
84
+ 'statusPassed' => __( 'Passed', 'cookie-notice' ),
85
+ 'statusFailed' => __( 'Failed', 'cookie-notice' ),
86
+ 'paidMonth' => __( 'monthly', 'cookie-notice' ),
87
+ 'paidYear' => __( 'yearly', 'cookie-notice' ),
88
+ 'pricingMonthly' => $this->pricing_monthly,
89
+ 'pricingYearly' => $this->pricing_yearly,
90
+ 'complianceStatus' => $cn->get_status(),
91
+ 'complianceFailed' => __( '<em>Compliance Failed!</em>Your website does not achieve minimum viable compliance. <b><a href="#" class="cn-sign-up">Sign up to Cookie Compliance</a></b> to bring your site into compliance with the latest data privacy rules and regulations.', 'cookie-notice' ),
92
+ 'compliancePassed' => __( '<em>Compliance Passed!</em>Congratulations. Your website meets minimum viable compliance.', 'cookie-notice' ),
93
+ 'licensesAvailable' => __( 'available', 'cookie-notice' ),
94
+ 'invalidFields' => __( 'Please fill all the required fields.', 'cookie-notice' )
95
  );
96
+
97
  // delete the show modal transient
98
+ if ( $network )
99
+ delete_site_transient( 'cn_show_welcome' );
100
+ else
101
+ delete_transient( 'cn_show_welcome' );
102
 
103
  wp_localize_script(
104
  'cookie-notice-welcome',
108
 
109
  wp_enqueue_style( 'cookie-notice-welcome', plugins_url( '../css/admin-welcome.css', __FILE__ ) );
110
  }
111
+
112
  /**
113
  * Add one or more classes to the body tag in the dashboard.
114
  *
117
  */
118
  public function admin_body_class( $classes ) {
119
  $classes .= ' folded';
120
+
121
  return $classes;
122
  }
123
 
124
  /**
125
  * Send user to the welcome page on first activation.
126
  *
127
+ * @global string $pagenow
128
+ *
129
  * @return void
130
  */
131
  public function welcome() {
132
  global $pagenow;
133
+
134
  if ( $pagenow != 'admin.php' )
135
  return;
136
+
137
  if ( isset( $_GET['page'] ) && $_GET['page'] !== 'cookie-notice' )
138
  return;
139
 
140
+ // bail if bulk activating or within an iframe
141
+ if ( isset( $_GET['activate-multi'] ) || defined( 'IFRAME_REQUEST' ) )
142
  return;
143
 
144
+ if ( ( isset( $_GET['action'] ) && 'upgrade-plugin' == $_GET['action'] ) && ( isset( $_GET['plugin'] ) && strstr( $_GET['plugin'], 'cookie-notice.php' ) ) )
145
  return;
146
 
147
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
148
  add_action( 'admin_footer', array( $this, 'admin_footer' ) );
149
+
150
  // add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
151
  }
152
+
153
  /**
154
  * Welcome modal container.
155
+ *
156
+ * @return void
157
  */
158
  public function admin_footer() {
159
  echo '<button id="cn-modal-trigger" style="display:none;"></button>';
160
  }
161
+
162
  /**
163
  * Output the welcome screen.
164
  *
171
 
172
  $this->welcome_screen( $screen );
173
  }
174
+
175
  /**
176
  * Render welcome screen sidebar step.
177
+ *
178
+ * @param int|string $screen
179
+ * @param bool $echo
180
+ * @return string|void
181
  */
182
  public function welcome_screen( $screen, $echo = true ) {
 
 
183
  if ( ! current_user_can( 'install_plugins' ) )
184
  wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
185
 
186
  $sidebars = array( 'about', 'login', 'register', 'configure', 'select_plan', 'success' );
187
  $steps = array( 1, 2, 3, 4 );
188
  $screens = array_merge( $sidebars, $steps );
 
 
189
  $screen = ! empty( $screen ) && in_array( $screen, $screens ) ? $screen : ( isset( $_REQUEST['screen'] ) && in_array( $_REQUEST['screen'], $screens ) ? $_REQUEST['screen'] : '' );
190
 
191
  if ( empty( $screen ) )
192
  wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
193
 
194
+ if ( wp_doing_ajax() && ! check_ajax_referer( 'cookie-notice-welcome', 'nonce' ) )
195
  wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
196
 
197
  // get token data
198
+ // $token_data = get_transient( 'cookie_notice_app_token' );
199
 
200
  // step screens
201
  if ( in_array( $screen, $steps ) ) {
204
 
205
  if ( $screen == 1 ) {
206
  $html .= $this->welcome_screen( 'about', false );
207
+
208
  $html .= '
209
  <div class="cn-content cn-sidebar-visible">
210
  <div class="cn-inner">
227
  <button type="button" class="cn-btn cn-btn-lg cn-btn-transparent cn-skip-button">' . __( 'Skip for now', 'cookie-notice' ) . '</button>
228
  </div>
229
  ';
230
+
231
  $html .= '
232
  </div>
233
  </div>
234
  </div>';
 
235
  } elseif ( $screen == 2 ) {
236
  $html .= $this->welcome_screen( 'configure', false );
237
 
241
  </div>';
242
  } elseif ( $screen == 3 ) {
243
  // get options
244
+ // $app_config = get_transient( 'cookie_notice_app_config' );
245
 
246
  $html .= $this->welcome_screen( 'register', false );
247
+
248
  $html .= '
249
  <div class="cn-content cn-sidebar-visible">
250
  <div class="cn-inner">
258
  <div class="cn-billing-wrapper cn-radio-wrapper">
259
  <label for="cn_billing_monthly"><input id="cn_billing_monthly" type="radio" name="cn_billing" value="monthly" checked><span><span>' . __( 'Billing Monthly', 'cookie-notice' ) . '</span><span class="cn-plan-overlay"></span></span></label><label for="cn_billing_yearly"><input id="cn_billing_yearly" type="radio" name="cn_billing" value="yearly"><span><span>' . __( 'Billing Yearly', 'cookie-notice' ) . '</span> <span class="cn-price-off">(' . __( '15% off', 'cookie-notice' ) . ')</span><span class="cn-plan-overlay"></span></span></label>
260
  </div>
261
+
262
  $html .= '
263
  <div class="cn-hero-image">
264
  <div class="cn-flex-item">
295
  </div>';
296
  */
297
 
298
+ $html .= '
299
  <h3 class="cn-pricing-select">' . __( 'Compliance Plans', 'cookie-notice' ) . ':</h3>
300
  <div class="cn-pricing-type cn-radio-wrapper">
301
  <div>
317
  <p class="cn-included"><span class="cn-icon"></span>' . __( 'GDPR, CCPA, ePrivacy, PECR compliance', 'cookie-notice' ) . '</p>
318
  <p class="cn-included"><span class="cn-icon"></span>' . __( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
319
  <p class="cn-excluded"><span class="cn-icon"></span>' . __( '<b>1,000</b> visits / month', 'cookie-notice' ) . '</p>
320
+ <p class="cn-excluded"><span class="cn-icon"></span>' . __( '<b>30 days</b> consent storage', 'cookie-notice' ) . '</p>
321
  <p class="cn-excluded"><span class="cn-icon"></span>' . __( '<b>1 additional</b> language', 'cookie-notice' ) . '</p>
322
  <p class="cn-excluded"><span class="cn-icon"></span>' . __( '<b>Basic</b> Support', 'cookie-notice' ) . '</p>
323
  </div>
346
  <p class="cn-included"><span class="cn-icon"></span>' . __( 'GDPR, CCPA, ePrivacy, PECR compliance', 'cookie-notice' ) . '</p>
347
  <p class="cn-included"><span class="cn-icon"></span>' . __( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
348
  <p class="cn-included"><span class="cn-icon"></span>' . __( '<b>Unlimited</b> visits', 'cookie-notice' ) . '</p>
349
+ <p class="cn-included"><span class="cn-icon"></span>' . __( '<b>Lifetime</b> consent storage', 'cookie-notice' ) . '</p>
350
  <p class="cn-included"><span class="cn-icon"></span>' . __( '<b>Unlimited</b> languages', 'cookie-notice' ) . '</p>
351
  <p class="cn-included"><span class="cn-icon"></span>' . __( '<b>Premium</b> Support', 'cookie-notice' ) . '</p>
352
  </div>
359
  <div class="cn-buttons">
360
  <button type="button" class="cn-btn cn-btn-lg cn-btn-transparent cn-skip-button">' . __( "I don’t want to create an account now", 'cookie-notice' ) . '</button>
361
  </div>';
362
+
 
363
  $html .= '
364
  </div>
365
  </div>
366
  </div>';
 
367
  } elseif ( $screen == 4 ) {
368
  $html .= $this->welcome_screen( 'success', false );
369
+
370
  $html .= '
371
  <div class="cn-content cn-sidebar-visible">
372
  <div class="cn-inner">
377
  <p>' . __( 'Log in to your Cookie Compliance&trade; account and continue configuring your Privacy Experience.', 'cookie-notice' ) . '</p>
378
  </div>
379
  <div class="cn-buttons">
380
+ <a href="' . Cookie_Notice()->get_url( 'login' ) . '" class="cn-btn cn-btn-lg" target="_blank">' . __( 'Go to Application', 'cookie-notice' ) . '</a>
381
  </div>
382
  </div>
383
  </div>
399
  <div class="cn-header">
400
  <div class="cn-top-bar">
401
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
402
+ </div>
403
  </div>
404
  <div class="cn-body">
405
  <h2>' . __( 'Compliance check', 'cookie-notice' ) . '</h2>
428
  <div class="cn-header">
429
  <div class="cn-top-bar">
430
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
431
+ </div>
432
  </div>
433
  <div class="cn-body">
434
  <h2>' . __( 'Live Setup', 'cookie-notice' ) . '</h2>
526
  <div class="cn-header">
527
  <div class="cn-top-bar">
528
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
529
+ </div>
530
  </div>
531
  <div class="cn-body">
532
  <h2>' . __( 'Compliance account', 'cookie-notice' ) . '</h2>
624
 
625
  $html .= '
626
  </form>
627
+ </div>
 
 
628
  </div>
629
  </div>';
630
  } elseif ( $screen === 'login' ) {
634
  <div class="cn-header">
635
  <div class="cn-top-bar">
636
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
637
+ </div>
638
  </div>
639
  <div class="cn-body">
640
  <h2>' . __( 'Compliance Sign in', 'cookie-notice' ) . '</h2>
656
  <div class="cn-field cn-field-submit cn-nav">
657
  <button type="submit" class="cn-btn cn-screen-button" tabindex="4" ' . /* data-screen="4" */ '><span class="cn-spinner"></span>' . __( 'Sign in', 'cookie-notice' ) . '</button>
658
  </div>';
659
+
660
  // get site language
661
  $locale = get_locale();
662
  $locale_code = explode( '_', $locale );
670
  </form>
671
  <p>' . __( 'Don\'t have an account yet?', 'cookie-notice' ) . ' <a href="#" class="cn-screen-button" data-screen="register">' . __( 'Sign up', 'cookie-notice' ) . '</a></p>
672
  </div>
673
+ </div>
 
 
674
  <div id="cn-accordion-billing" class="cn-accordion-item cn-form-container cn-collapsed cn-disabled" tabindex="-1">
675
  <div class="cn-accordion-header cn-form-header">
676
  <button class="cn-accordion-button" type="button">2. ' . __( 'Select Plan', 'cookie-notice' ) . '</button>
690
  <div class="cn-field cn-fieldset" id="cn_submit_free">
691
  <button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . __( 'Confirm', 'cookie-notice' ) . '</button>
692
  </div>
693
+
694
  <div class="cn-field cn-fieldset cn-hidden" id="cn_submit_pro">
695
  <input type="hidden" name="cn_payment_identifier" value="" />
696
  <div class="cn-field cn-field-radio">
722
  <div id="cn_paypal_button"></div>
723
  </div>
724
  </div>
725
+
726
  <div class="cn-field cn-fieldset cn-hidden" id="cn_submit_license">
727
  <div class="cn-field cn-field-select" id="cn-subscriptions-list">
728
  <label for="cn-subscription-select">' . __( 'Select subscription', 'cookie-notice' ) . '​</label>
746
  <div class="cn-header">
747
  <div class="cn-top-bar">
748
  <div class="cn-logo"><img src="' . plugins_url( '../img/cookie-notice-logo.png', __FILE__ ) . '" alt="Cookie Notice logo" /></div>
749
+ </div>
750
  </div>
751
  <div class="cn-body">
752
  <h2>' . __( 'Success!', 'cookie-notice' ) . '</h2>
753
+ <div class="cn-lead"><p><b>' . __( 'You have successfully upgraded your website to Cookie Compliance&trade;', 'cookie-notice' ) . '</b></p><p>' . sprintf( __( 'Go to Cookie Compliance&trade; application now. Or access it anytime from your <a href="%s">Cookie Notice settings page</a>.', 'cookie-notice' ), esc_url( Cookie_Notice()->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice' ) : admin_url( 'admin.php?page=cookie-notice' ) ) ) . '</p></div>
754
  </div>';
755
  }
756
 
 
757
  $html .= '
758
  <div class="cn-footer">';
759
  /*
773
  </div>
774
  </div>
775
  </div>';
 
776
  }
777
 
778
  if ( $echo )
780
  else
781
  return $html;
782
 
783
+ if ( wp_doing_ajax() )
784
  exit();
785
  }
786
  }
js/admin-dashboard.js CHANGED
@@ -1,67 +1,63 @@
1
- (function ($) {
2
-
3
- // ready event
4
- $(function () {
5
-
6
- var charts = cnDashboardArgs.charts;
7
- // console.log(charts);
8
-
9
- if (Object.entries(charts).length > 0) {
10
- for (const [key, config] of Object.entries(charts)) {
11
-
12
- var canvas = document.getElementById('cn-' + key + '-chart');
13
- // console.log(canvas);
14
-
15
- // options per chart type
16
- var options = {
17
- doughnut: {
18
- responsive: true,
19
- plugins: {
20
- legend: {
21
- position: 'top',
22
- },
23
- },
24
- hover: {
25
- mode: 'label'
26
- },
27
- layout: {
28
- padding: 0
29
- }
30
- },
31
- line: {
32
- scales: {
33
- xAxes: [{
34
- afterTickToLabelConversion: function (data) {
35
-
36
-
37
- var xLabels = data.ticks;
38
-
39
- xLabels.forEach(function (labels, i) {
40
- if (i % 2 == 1) {
41
- xLabels[i] = '';
42
- }
43
- });
44
- }
45
- }]
46
- }
47
- }
48
- }
49
-
50
- // console.log(config);
51
-
52
- if (canvas) {
53
- config.options = options.hasOwnProperty(config.type) ? options[config.type] : {};
54
-
55
- var chart = new Chart(canvas, config);
56
-
57
- // console.log(config);
58
- // console.log(chart);
59
-
60
- chart.update();
61
- }
62
-
63
- }
64
- }
65
- });
66
-
67
- })(jQuery);
1
+ ( function( $ ) {
2
+
3
+ // ready event
4
+ $( function() {
5
+ var charts = cnDashboardArgs.charts;
6
+
7
+ if ( Object.entries(charts).length > 0 ) {
8
+ for ( const [key, config] of Object.entries( charts ) ) {
9
+ // create canvas
10
+ var canvas = document.getElementById( 'cn-' + key + '-chart' );
11
+
12
+ if ( canvas ) {
13
+ // options per chart type
14
+ var options = {
15
+ doughnut: {
16
+ responsive: true,
17
+ plugins: {
18
+ legend: {
19
+ position: 'top',
20
+ }
21
+ },
22
+ hover: {
23
+ mode: 'label'
24
+ },
25
+ layout: {
26
+ padding: 0
27
+ }
28
+ },
29
+ line: {
30
+ scales: {
31
+ x: {
32
+ display: true,
33
+ title: {
34
+ display: false
35
+ }
36
+ },
37
+ y: {
38
+ display: true,
39
+ grace: 0,
40
+ beginAtZero: true,
41
+ title: {
42
+ display: false
43
+ },
44
+ ticks: {
45
+ precision: 0,
46
+ maxTicksLimit: 12
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+
53
+ config.options = options.hasOwnProperty( config.type ) ? options[config.type] : {};
54
+
55
+ var chart = new Chart( canvas, config );
56
+
57
+ chart.update();
58
+ }
59
+ }
60
+ }
61
+ } );
62
+
63
+ } )( jQuery );
 
 
 
 
js/admin-notice.js CHANGED
@@ -1,39 +1,39 @@
1
- ( function( $ ) {
2
-
3
- // ready event
4
- $( function() {
5
- // Save dismiss state // .is-dismissible
6
- $( '.cn-notice' ).on( 'click', '.notice-dismiss, .cn-notice-dismiss', function( e ) {
7
-
8
- var notice_action = 'dismiss';
9
- var param = '';
10
-
11
- if ( $( e.currentTarget ).hasClass( 'cn-approve' ) )
12
- notice_action = 'approve';
13
- else if ( $( e.currentTarget ).hasClass( 'cn-delay' ) )
14
- notice_action = 'delay';
15
- else if ( $( e.delegateTarget ).hasClass( 'cn-threshold' ) ) {
16
- notice_action = 'threshold';
17
-
18
- var delay = $( e.delegateTarget ).find( '.cn-notice-text' ).data( 'delay' );
19
-
20
- param = parseInt( delay );
21
- }
22
-
23
- $.ajax( {
24
- url: cnArgsNotice.ajaxURL,
25
- type: 'POST',
26
- dataType: 'json',
27
- data: {
28
- action: 'cn_dismiss_notice',
29
- notice_action: notice_action,
30
- nonce: cnArgsNotice.nonce,
31
- param: param
32
- }
33
- } );
34
-
35
- $( e.delegateTarget ).slideUp( 'fast' );
36
- } );
37
- } );
38
-
39
  } )( jQuery );
1
+ ( function( $ ) {
2
+
3
+ // ready event
4
+ $( function() {
5
+ // save dismiss state // .is-dismissible
6
+ $( '.cn-notice' ).on( 'click', '.notice-dismiss, .cn-notice-dismiss', function( e ) {
7
+ var notice_action = 'dismiss';
8
+ var param = '';
9
+
10
+ if ( $( e.currentTarget ).hasClass( 'cn-approve' ) )
11
+ notice_action = 'approve';
12
+ else if ( $( e.currentTarget ).hasClass( 'cn-delay' ) )
13
+ notice_action = 'delay';
14
+ else if ( $( e.delegateTarget ).hasClass( 'cn-threshold' ) ) {
15
+ notice_action = 'threshold';
16
+
17
+ var delay = $( e.delegateTarget ).find( '.cn-notice-text' ).data( 'delay' );
18
+
19
+ param = parseInt( delay );
20
+ }
21
+
22
+ $.ajax( {
23
+ url: cnArgsNotice.ajaxURL,
24
+ type: 'POST',
25
+ dataType: 'json',
26
+ data: {
27
+ action: 'cn_dismiss_notice',
28
+ notice_action: notice_action,
29
+ nonce: cnArgsNotice.nonce,
30
+ param: param,
31
+ cn_network: cnArgsNotice.network
32
+ }
33
+ } );
34
+
35
+ $( e.delegateTarget ).slideUp( 'fast' );
36
+ } );
37
+ } );
38
+
39
  } )( jQuery );
js/admin-plugins.js CHANGED
@@ -1,66 +1,69 @@
1
- ( function( $ ) {
2
-
3
- // ready event
4
- $( function() {
5
- // cancel deactivation
6
- $( document ).on( 'click', '.cn-deactivate-plugin-cancel', function( e ) {
7
- tb_remove();
8
-
9
- return false;
10
- } );
11
-
12
- // simple deactivation
13
- $( document ).on( 'click', '.cn-deactivate-plugin-simple', function( e ) {
14
- // display spinner
15
- $( '#cn-deactivation-footer .spinner' ).addClass( 'is-active' );
16
- } );
17
-
18
- // deactivation with sending data
19
- $( document ).on( 'click', '.cn-deactivate-plugin-data', function( e ) {
20
- var spinner = $( '#cn-deactivation-footer .spinner' ),
21
- url = $( this ).attr( 'href' );
22
-
23
- // display spinner
24
- spinner.addClass( 'is-active' );
25
-
26
- // submit data
27
- $.post( ajaxurl, {
28
- action: 'cn-deactivate-plugin',
29
- option_id: $( 'input[name="cn_deactivation_option"]:checked' ).val(),
30
- other: $( 'textarea[name="cn_deactivation_other"]' ).val(),
31
- nonce: cnArgsPlugins.nonce
32
- } ).done( function( response ) {
33
- // deactivate plugin
34
- window.location.href = url;
35
- } ).fail( function() {
36
- // deactivate plugin
37
- window.location.href = url;
38
- } );
39
-
40
- return false;
41
- } );
42
-
43
- // click on deactivation link
44
- $( document ).on( 'click', '.cn-deactivate-plugin-modal', function( e ) {
45
- var modalBox = $( '#cn-deactivation-container' ).closest( '#TB_window' );
46
-
47
- tb_show( cnArgsPlugins.deactivate, '#TB_inline?inlineId=cn-deactivation-modal&modal=false' );
48
-
49
- if ( modalBox.length > 0 ) {
50
- $( modalBox ).addClass( 'cn-deactivation-modal' );
51
- $( modalBox ).find( '#TB_closeWindowButton' ).on( 'blur' );
52
- }
53
-
54
- return false;
55
- } );
56
-
57
- // change radio
58
- $( document ).on( 'change', 'input[name="cn_deactivation_option"]', function( e ) {
59
- if ( $( this ).val() === '6' )
60
- $( '.cn-deactivation-textarea textarea' ).prop( 'disabled', false );
61
- else
62
- $( '.cn-deactivation-textarea textarea' ).prop( 'disabled', true );
63
- } );
64
- } );
65
-
 
 
 
66
  } )( jQuery );
1
+ ( function( $ ) {
2
+
3
+ // ready event
4
+ $( function() {
5
+ // cancel deactivation
6
+ $( document ).on( 'click', '.cn-deactivate-plugin-cancel', function( e ) {
7
+ tb_remove();
8
+
9
+ return false;
10
+ } );
11
+
12
+ // simple deactivation
13
+ $( document ).on( 'click', '.cn-deactivate-plugin-simple', function( e ) {
14
+ // display spinner
15
+ $( '#cn-deactivation-footer .spinner' ).addClass( 'is-active' );
16
+ } );
17
+
18
+ // deactivation with sending data
19
+ $( document ).on( 'click', '.cn-deactivate-plugin-data', function( e ) {
20
+ var spinner = $( '#cn-deactivation-footer .spinner' ),
21
+ url = $( this ).attr( 'href' );
22
+
23
+ // display spinner
24
+ spinner.addClass( 'is-active' );
25
+
26
+ // submit data
27
+ $.post( ajaxurl, {
28
+ action: 'cn-deactivate-plugin',
29
+ option_id: $( 'input[name="cn_deactivation_option"]:checked' ).val(),
30
+ other: $( 'textarea[name="cn_deactivation_other"]' ).val(),
31
+ nonce: cnArgsPlugins.nonce
32
+ } ).done( function( response ) {
33
+ // deactivate plugin
34
+ window.location.href = url;
35
+ } ).fail( function() {
36
+ // deactivate plugin
37
+ window.location.href = url;
38
+ } );
39
+
40
+ return false;
41
+ } );
42
+
43
+ // click on deactivation link
44
+ $( document ).on( 'click', '.cn-deactivate-plugin-modal', function( e ) {
45
+ var modalBox = $( '#cn-deactivation-container' ).closest( '#TB_window' );
46
+
47
+ tb_show( cnArgsPlugins.deactivate, '#TB_inline?inlineId=cn-deactivation-modal&modal=false' );
48
+
49
+ if ( modalBox.length > 0 ) {
50
+ $( modalBox ).addClass( 'cn-deactivation-modal' );
51
+ $( modalBox ).find( '#TB_closeWindowButton' ).on( 'blur' );
52
+ }
53
+
54
+ return false;
55
+ } );
56
+
57
+ // change radio
58
+ $( document ).on( 'change', 'input[name="cn_deactivation_option"]', function( e ) {
59
+ var last = $( 'input[name="cn_deactivation_option"]' ).last().get( 0 );
60
+
61
+ // last element?
62
+ if ( $( this ).get( 0 ) === last )
63
+ $( '.cn-deactivation-textarea textarea' ).prop( 'disabled', false );
64
+ else
65
+ $( '.cn-deactivation-textarea textarea' ).prop( 'disabled', true );
66
+ } );
67
+ } );
68
+
69
  } )( jQuery );
js/admin-welcome.js CHANGED
@@ -1,17 +1,17 @@
1
- ( function ( $ ) {
2
 
3
  // ready event
4
- $( function () {
5
  var btClient = false;
6
  var btCreditCardsInitialized = false;
7
  var btPayPalInitialized = false;
8
 
9
- var btInit = function () {
10
  var result = btInitToken();
11
 
12
  if ( result !== false && btCreditCardsInitialized === false ) {
13
- // AJAX was successful
14
- result.done( function ( response ) {
15
  // token received
16
  try {
17
  // parse response
@@ -27,14 +27,14 @@
27
  } catch ( e ) {
28
  btGatewayFail( 'btInit catch' );
29
  }
30
- // AJAX failed
31
- } ).fail( function () {
32
  btGatewayFail( 'btInit AJAX failed' );
33
  } );
34
  }
35
  }
36
 
37
- var btInitToken = function () {
38
  // payment screen?
39
  var paymentEl = $( '.cn-sidebar form[data-action="payment"]' );
40
 
@@ -43,15 +43,21 @@
43
  paymentEl.addClass( 'cn-form-disabled' );
44
 
45
  if ( typeof braintree !== 'undefined' ) {
 
 
 
 
 
 
 
 
 
 
46
  return $.ajax( {
47
  url: cnWelcomeArgs.ajaxURL,
48
  type: 'POST',
49
  dataType: 'html',
50
- data: {
51
- action: 'cn_api_request',
52
- request: 'get_bt_init_token',
53
- nonce: cnWelcomeArgs.nonce
54
- }
55
  } );
56
  } else
57
  return false;
@@ -59,9 +65,7 @@
59
  return false;
60
  }
61
 
62
- var btInitPaymentMethod = function ( type ) {
63
- // console.log( 'btInitPaymentMethod' );
64
-
65
  if ( btClient !== false ) {
66
  if ( type === 'credit_card' && btCreditCardsInitialized === false ) {
67
  $( 'form.cn-form[data-action="payment"]' ).addClass( 'cn-form-disabled' );
@@ -76,9 +80,7 @@
76
  btGatewayFail( 'btInitPaymentMethod btClient is false' );
77
  }
78
 
79
- var btCreditCardsInit = function ( clientInstance ) {
80
- // console.log( 'btCreditCardsInit' );
81
-
82
  return braintree.hostedFields.create( {
83
  client: clientInstance,
84
  styles: {
@@ -111,16 +113,14 @@
111
  } );
112
  }
113
 
114
- var btHostedFieldsInstance = function ( hostedFieldsInstance ) {
115
- // console.log( 'btHostedFieldsInstance' );
116
-
117
  btCreditCardsInitialized = true;
118
 
119
  var form = $( 'form.cn-form[data-action="payment"]' );
120
 
121
  form.removeClass( 'cn-form-disabled' );
122
 
123
- form.on( 'submit', function () {
124
  if ( form.hasClass( 'cn-payment-in-progress' ) )
125
  return false;
126
 
@@ -134,7 +134,7 @@
134
  var state = hostedFieldsInstance.getState();
135
 
136
  // check hosted fields
137
- Object.keys( state.fields ).forEach( function ( field ) {
138
  if ( ! state.fields[field].isValid ) {
139
  $( state.fields[field].container ).addClass( 'braintree-hosted-fields-invalid' );
140
 
@@ -143,7 +143,7 @@
143
  } );
144
 
145
  if ( invalidForm ) {
146
- setTimeout( function () {
147
  cnDisplayError( cnWelcomeArgs.invalidFields, form );
148
 
149
  // spin the spinner, if exists
@@ -154,11 +154,7 @@
154
  return false;
155
  }
156
 
157
- hostedFieldsInstance.tokenize( function ( err, payload ) {
158
-
159
- console.log( 'btHostedFieldsInstance' );
160
- console.log( payload );
161
-
162
  if ( err ) {
163
  cnDisplayError( cnWelcomeArgs.error );
164
 
@@ -176,33 +172,25 @@
176
  } );
177
  }
178
 
179
- var btPaypalCheckoutInit = function ( clientInstance ) {
180
- // console.log( 'btPaypalCheckoutInit' );
181
-
182
  return braintree.paypalCheckout.create( {
183
  client: clientInstance
184
  } );
185
  }
186
 
187
- var btPaypalCheckoutSDK = function ( paypalCheckoutInstance ) {
188
- // console.log( 'btPaypalCheckoutSDK' );
189
-
190
  return paypalCheckoutInstance.loadPayPalSDK( {
191
  vault: true,
192
  intent: 'tokenize'
193
  } );
194
  }
195
 
196
- var btPaypalCheckoutInstance = function ( paypalCheckoutInstance ) {
197
- // console.log( 'btPaypalCheckoutInstance' );
198
-
199
  var form = $( 'form.cn-form[data-action="payment"]' );
200
 
201
  return paypal.Buttons( {
202
  fundingSource: paypal.FUNDING.PAYPAL,
203
- createBillingAgreement: function () {
204
- // console.log( 'createBillingAgreement' );
205
-
206
  form.addClass( 'cn-form-disabled' );
207
 
208
  return paypalCheckoutInstance.createPayment( {
@@ -211,62 +199,45 @@
211
  currency: 'EUR'
212
  } );
213
  },
214
- onApprove: function ( data, actions ) {
215
- // console.log( 'onApprove' );
216
-
217
- return paypalCheckoutInstance.tokenizePayment( data ).then( function ( payload ) {
218
-
219
- console.log( 'btPaypalCheckoutInstance' );
220
- console.log( payload );
221
-
222
  form.addClass( 'cn-payment-in-progress' );
223
  form.find( 'input[name="payment_nonce"]' ).val( payload.nonce );
224
  form.find( 'input[name="cn_payment_identifier"]' ).val( payload.details.email );
225
 
226
- // console.log( 'onApprove inside' );
227
- // console.log( $( '#cn_submit_pro' ).find( '.cn-screen-button[data-screen="4"]' ) );
228
-
229
  $( '#cn_submit_pro' ).find( '.cn-screen-button[data-screen="4"]' ).trigger( 'click' );
230
  } );
231
  },
232
- onCancel: function ( data ) {
233
- // console.log( 'onCancel' );
234
-
235
  form.removeClass( 'cn-form-disabled' );
236
  },
237
- onError: function ( err ) {
238
- // console.log( 'onError' );
239
-
240
  form.removeClass( 'cn-form-disabled' );
241
  }
242
  } ).render( '#cn_paypal_button' );
243
  }
244
 
245
- var btPaypalCheckoutButton = function () {
246
- // console.log( 'btPaypalCheckoutButton' );
247
-
248
  btPayPalInitialized = true;
249
 
250
  $( 'form.cn-form[data-action="payment"]' ).removeClass( 'cn-form-disabled' );
251
  }
252
 
253
- var btGatewayFail = function ( error ) {
254
- // console.log( 'btGatewayFail' );
255
-
256
  if ( typeof error !== 'undefined' )
257
  console.log( error );
258
 
259
  cnDisplayError( cnWelcomeArgs.error );
260
  }
261
 
262
- var cnDisplayError = function ( message, form ) {
263
  if ( typeof form === 'undefined' )
264
  form = $( 'form.cn-form[data-action="payment"]' );
265
 
266
  form.find( '.cn-form-feedback' ).html( '<p class="cn-error">' + message + '</p>' ).removeClass( 'cn-hidden' );
267
  }
268
 
269
- var cnWelcomeScreen = function ( target ) {
270
  var screen = $( target ).data( 'screen' );
271
  var steps = [1, 2, 3, 4];
272
  var sidebars = ['login', 'register', 'configure', 'payment'];
@@ -277,17 +248,21 @@
277
  nonce: cnWelcomeArgs.nonce
278
  };
279
 
280
- if ( $.inArray( screen, steps ) != - 1 ) {
281
  var container = $( '.cn-welcome-wrap' );
282
 
283
  requestData.screen = screen;
284
- } else if ( $.inArray( screen, sidebars ) != - 1 ) {
285
  var container = $( '.cn-sidebar' );
286
 
287
  requestData.screen = screen;
288
  } else
289
  return false;
290
 
 
 
 
 
291
  // add loading overlay
292
  $( container ).addClass( 'cn-loading' );
293
 
@@ -296,11 +271,11 @@
296
  type: 'POST',
297
  dataType: 'html',
298
  data: requestData
299
- } ).done( function ( response ) {
300
  $( container ).replaceWith( response );
301
- } ).fail( function ( jqXHR, textStatus, errorThrown ) {
302
  //
303
- } ).always( function ( response ) {
304
  // remove spinner
305
  $( container ).removeClass( 'cn-loading' );
306
 
@@ -313,7 +288,7 @@
313
  return this;
314
  };
315
 
316
- var cnWelcomeForm = function ( form ) {
317
  var formAction = $( form[0] ).data( 'action' );
318
  var formResult = null;
319
  var formData = {
@@ -328,7 +303,7 @@
328
  formData.request = formAction;
329
 
330
  // convert form data to object
331
- $( form[0] ).serializeArray().map( function ( x ) {
332
  // exception for checkboxes
333
  if ( x.name === 'cn_laws' ) {
334
  var arrayVal = typeof formData[x.name] !== 'undefined' ? formData[x.name] : [];
@@ -336,11 +311,14 @@
336
  arrayVal.push( x.value );
337
 
338
  formData[x.name] = arrayVal;
339
- } else {
340
  formData[x.name] = x.value;
341
- }
342
  } );
343
 
 
 
 
 
344
  formResult = $.ajax( {
345
  url: cnWelcomeArgs.ajaxURL,
346
  type: 'POST',
@@ -352,7 +330,7 @@
352
  };
353
 
354
  // handle screen loading
355
- $( document ).on( 'click', '.cn-screen-button', function ( e ) {
356
  var form = $( e.target ).closest( 'form' );
357
  var result = false;
358
 
@@ -369,7 +347,7 @@
369
  var formAction = formDataset.hasOwnProperty( 'action' ) ? formDataset.action : '';
370
 
371
  // get form data
372
- $( form[0] ).serializeArray().map( function ( x ) {
373
  // exception for checkboxes
374
  if ( x.name === 'cn_laws' ) {
375
  var arrayVal = typeof formData[x.name] !== 'undefined' ? formData[x.name] : [];
@@ -377,14 +355,12 @@
377
  arrayVal.push( x.value );
378
 
379
  formData[x.name] = arrayVal;
380
- } else {
381
  formData[x.name] = x.value;
382
- }
383
  } );
384
 
385
  // payment?
386
  if ( formAction === 'payment' ) {
387
-
388
  // free
389
  if ( formData.plan === 'free' ) {
390
  // load screen
@@ -399,30 +375,34 @@
399
  // disable form
400
  if ( paymentEl.length )
401
  paymentEl.addClass( 'cn-form-disabled' );
402
-
403
  // get subscription ID
404
  var subscriptionID = formData.hasOwnProperty( 'cn_subscription_id' ) ? parseInt( formData.cn_subscription_id ) : 0;
405
 
 
 
 
 
 
 
 
 
 
 
 
406
  // assign license request
407
  result = $.ajax( {
408
  url: cnWelcomeArgs.ajaxURL,
409
  type: 'POST',
410
  dataType: 'json',
411
- data: {
412
- action: 'cn_api_request',
413
- request: 'use_license',
414
- subscriptionID: subscriptionID,
415
- nonce: cnWelcomeArgs.nonce
416
- }
417
  } );
418
-
419
  // process license
420
- result.done( function ( response ) {
421
  // error
422
  if ( response.hasOwnProperty( 'error' ) ) {
423
  cnDisplayError( response.error, $( form[0] ) );
424
-
425
- // console.log( response.error );
426
 
427
  return false;
428
  // message
@@ -435,17 +415,16 @@
435
  return result;
436
  }
437
  } );
438
-
439
  // remove spinner
440
- result.always( function ( response ) {
441
  if ( $( e.target ).find( '.cn-spinner' ).length )
442
  $( e.target ).find( '.cn-spinner' ).removeClass( 'spin' );
443
-
444
  // enable form
445
  if ( paymentEl.length )
446
  paymentEl.removeClass( 'cn-form-disabled' );
447
  } );
448
-
449
  // pro
450
  } else {
451
  // only credit cards
@@ -455,11 +434,10 @@
455
  return false;
456
  }
457
  }
458
-
459
  // other forms
460
  } else
461
  e.preventDefault();
462
-
463
  // break here on license payment
464
  if ( formAction === 'payment' && formData.plan === 'license' )
465
  return result;
@@ -467,25 +445,24 @@
467
  // get form and process it
468
  result = cnWelcomeForm( form );
469
 
470
- result.done( function ( response ) {
471
  // error
472
  if ( response.hasOwnProperty( 'error' ) ) {
473
  cnDisplayError( response.error, $( form[0] ) );
474
 
475
  return false;
476
- // message
477
  } else if ( response.hasOwnProperty( 'message' ) ) {
478
  cnDisplayError( response.message, $( form[0] ) );
479
 
480
  return false;
481
- // all good
482
  } else {
483
  switch ( formAction ) {
484
  // logged in, go to success or billing
485
- case 'login' :
486
  // register complete, go to success or billing
487
- case 'register' :
488
-
489
  // if there are any subscriptions
490
  if ( response.hasOwnProperty( 'subscriptions' ) ) {
491
  var subscriptions = response.subscriptions;
@@ -530,11 +507,10 @@
530
 
531
  // init braintree after payment screen is loaded via AJAX
532
  btInit();
533
-
534
  break;
535
 
536
- case 'configure' :
537
- default :
538
  // load screen
539
  cnWelcomeScreen( e.target );
540
  break;
@@ -542,7 +518,7 @@
542
  }
543
  } );
544
 
545
- result.always( function ( response ) {
546
  if ( $( e.target ).find( '.cn-spinner' ).length )
547
  $( e.target ).find( '.cn-spinner' ).removeClass( 'spin' );
548
 
@@ -557,18 +533,18 @@
557
  } );
558
 
559
  //
560
- $( document ).on( 'screen-loaded', function () {
561
  var configureFields = $( '#cn-form-configure' ).serializeArray() || [];
562
  var frame = window.frames[ 'cn_iframe_id' ];
563
 
564
  if ( configureFields.length > 0 ) {
565
- $( configureFields ).each( function ( index, field ) {
566
  } );
567
  }
568
  } );
569
 
570
  // change payment method
571
- $( document ).on( 'change', 'input[name="method"]', function () {
572
  var input = $( this );
573
 
574
  $( '#cn_payment_method_credit_card, #cn_payment_method_paypal' ).toggle();
@@ -579,8 +555,8 @@
579
  btInitPaymentMethod( input.val() );
580
  } );
581
 
582
- //
583
- $( document ).on( 'click', '.cn-accordion > .cn-accordion-item .cn-accordion-button', function () {
584
  var accordionItem = $( this ).closest( '.cn-accordion-item' );
585
  var activeItem = $( this ).closest( '.cn-accordion' ).find( '.cn-accordion-item:not(.cn-collapsed)' );
586
 
@@ -593,17 +569,17 @@
593
  } );
594
 
595
  // live preview
596
- $( document ).on( 'change', 'input[name="cn_position"]', function () {
597
  var val = $( this ).val();
598
  var frame = window.frames['cn_iframe_id'];
599
 
600
  frame.contentWindow.postMessage( {call: 'position', value: val} );
601
  } );
602
 
603
- $( document ).on( 'change', 'input[name="cn_laws"]', function () {
604
  var val = [];
605
 
606
- $( 'input[name="cn_laws"]:checked' ).each( function () {
607
  val.push( $( this ).val() );
608
  } );
609
 
@@ -612,10 +588,10 @@
612
  frame.contentWindow.postMessage( {call: 'laws', value: val} );
613
  } );
614
 
615
- $( document ).on( 'change', 'input[name="cn_naming"]', function () {
616
  var val = [];
617
 
618
- $( 'input[name="cn_naming"]:checked' ).each( function () {
619
  val.push( $( this ).val() );
620
  } );
621
 
@@ -624,56 +600,56 @@
624
  frame.contentWindow.postMessage( {call: 'naming', value: val} );
625
  } );
626
 
627
- $( document ).on( 'change', 'input[name="cn_privacy_paper"]', function () {
628
  var val = $( this ).prop( 'checked' );
629
  var frame = window.frames['cn_iframe_id'];
630
 
631
  frame.contentWindow.postMessage( {call: 'privacy_paper', value: val} );
632
  } );
633
 
634
- $( document ).on( 'change', 'input[name="cn_privacy_contact"]', function () {
635
  var val = $( this ).prop( 'checked' );
636
  var frame = window.frames['cn_iframe_id'];
637
 
638
  frame.contentWindow.postMessage( {call: 'privacy_contact', value: val} );
639
  } );
640
 
641
- $( document ).on( 'change', 'input[name="cn_color_primary"]', function () {
642
  var val = $( this ).val();
643
  var frame = window.frames['cn_iframe_id'];
644
 
645
  frame.contentWindow.postMessage( {call: 'color_primary', value: val} );
646
  } );
647
 
648
- $( document ).on( 'change', 'input[name="cn_color_background"]', function () {
649
  var val = $( this ).val();
650
  var frame = window.frames['cn_iframe_id'];
651
 
652
  frame.contentWindow.postMessage( {call: 'color_background', value: val} );
653
  } );
654
 
655
- $( document ).on( 'change', 'input[name="cn_color_border"]', function () {
656
  var val = $( this ).val();
657
  var frame = window.frames['cn_iframe_id'];
658
 
659
  frame.contentWindow.postMessage( {call: 'color_border', value: val} );
660
  } );
661
 
662
- $( document ).on( 'change', 'input[name="cn_color_text"]', function () {
663
  var val = $( this ).val();
664
  var frame = window.frames['cn_iframe_id'];
665
 
666
  frame.contentWindow.postMessage( {call: 'color_text', value: val} );
667
  } );
668
 
669
- $( document ).on( 'change', 'input[name="cn_color_heading"]', function () {
670
  var val = $( this ).val();
671
  var frame = window.frames['cn_iframe_id'];
672
 
673
  frame.contentWindow.postMessage( {call: 'color_heading', value: val} );
674
  } );
675
 
676
- $( document ).on( 'change', 'input[name="cn_color_button_text"]', function () {
677
  var val = $( this ).val();
678
  var frame = window.frames['cn_iframe_id'];
679
 
@@ -681,7 +657,7 @@
681
  } );
682
 
683
  // handle monthly / yearly payment plan
684
- $( document ).on( 'change', 'input[name="cn_pricing_type"]', function () {
685
  // pricing plans
686
  var plansMonthly = cnWelcomeArgs.pricingMonthly;
687
  var plansYearly = cnWelcomeArgs.pricingYearly;
@@ -692,11 +668,10 @@
692
  var names = Object.keys( checked === 'yearly' ? plansYearly : plansMonthly );
693
  var pricing = Object.values( checked === 'yearly' ? plansYearly : plansMonthly );
694
 
695
- if ( checked === 'yearly' ) {
696
  $( '.cn-plan-period' ).text( cnWelcomeArgs.paidYear );
697
- } else {
698
  $( '.cn-plan-period' ).text( cnWelcomeArgs.paidMonth );
699
- }
700
 
701
  // replace options
702
  var i = 0;
@@ -704,20 +679,17 @@
704
  for ( var property in pricing ) {
705
  var option = pricingOptions[i];
706
 
707
- // console.log( option );
708
-
709
  $( option ).val( names[i] );
710
  $( option ).attr( 'data-price', pricing[i] );
711
- i ++;
712
  }
713
 
714
  // trigger plan selection
715
  $( 'select[name="cn_pricing_plan"]' ).trigger( 'change' );
716
-
717
  } );
718
 
719
  // handle pro plan selection
720
- $( document ).on( 'change', 'select[name="cn_pricing_plan"]', function () {
721
  var el = $( '#cn-pricing-plans' );
722
  var selected = $( el ).find( 'option:selected' );
723
 
@@ -730,12 +702,10 @@
730
  availablePlans = availablePlans.concat( Object.keys( cnWelcomeArgs.pricingMonthly ) );
731
  availablePlans = availablePlans.concat( Object.keys( cnWelcomeArgs.pricingYearly ) );
732
 
733
- var input = $( this ),
734
- inputVal = input.val();
735
-
736
- inputVal = availablePlans.indexOf( inputVal ) != - 1 ? inputVal : 'free';
737
 
738
- // console.log( inputVal );
739
 
740
  if ( inputVal === 'free' ) {
741
  $( '#cn_submit_free' ).removeClass( 'cn-hidden' );
@@ -753,7 +723,7 @@
753
  } );
754
 
755
  // handle free / pro / license selection
756
- $( document ).on( 'change', 'input[name="plan"]', function () {
757
  var input = $( this ),
758
  inputVal = input.val();
759
 
@@ -780,12 +750,12 @@
780
  } );
781
 
782
  // highlight form
783
- $( document ).on( 'click', 'input[name="cn_pricing"]', function () {
784
  $( '.cn-accordion .cn-accordion-item:first-child:not(.cn-collapsed)' ).focus();
785
  } );
786
 
787
  // select plan payment
788
- $( document ).on( 'change', 'input[name="cn_pricing"]', function () {
789
  var input = $( this ),
790
  inputVal = input.val();
791
 
@@ -812,7 +782,7 @@
812
 
813
  } );
814
 
815
- $( document ).on( 'ajaxComplete', function () {
816
  // color picker
817
  initSpectrum();
818
  } );
@@ -832,21 +802,20 @@
832
  modal = $( "#cn-modal-trigger" );
833
 
834
  if ( modal ) {
835
-
836
  $( "#cn-modal-trigger" ).modaal( {
837
  content_source: cnWelcomeArgs.ajaxURL + '?action=cn_welcome_screen' + '&nonce=' + cnWelcomeArgs.nonce + '&screen=1',
838
  type: 'ajax',
839
  width: 1600,
840
  custom_class: 'cn-modal',
841
  // is_locked: true
842
- ajax_success: function () {
843
  progressbar = $( document ).find( '.cn-progressbar' );
844
 
845
  if ( progressbar ) {
846
  timerId = initProgressBar( progressbar );
847
  }
848
  },
849
- before_close: function () {
850
  clearInterval( timerId );
851
 
852
  var currentStep = $( '.cn-welcome-wrap' );
@@ -857,7 +826,7 @@
857
  window.location.reload( true );
858
  }
859
  },
860
- after_close: function () {
861
  progressbar = $( document ).find( '.cn-progressbar' );
862
 
863
  $( progressbar ).progressbar( "destroy" );
@@ -866,7 +835,7 @@
866
 
867
  $( modal ).trigger( 'click' );
868
 
869
- $( document ).on( 'click', '.cn-skip-button', function ( e ) {
870
  $( '#modaal-close' ).trigger( 'click' );
871
  } );
872
  }
@@ -880,27 +849,20 @@
880
  timerId;
881
 
882
  if ( progressbar ) {
883
-
884
- $( document ).on( 'click', '.cn-screen-button', function ( e ) {
885
  e.preventDefault();
886
 
887
- // console.log( e );
888
-
889
  clearInterval( timerId );
890
  } );
891
 
892
  $( progressbar ).progressbar( {
893
  value: 5,
894
  max: 100,
895
- create: function ( event, ui ) {
896
- // console.log( event );
897
-
898
- timerId = setInterval( function () {
899
  // increment progress bar
900
  currentProgress += 5;
901
 
902
- // console.log( currentProgress );
903
-
904
  // update progressbar
905
  progressbar.progressbar( 'value', currentProgress );
906
 
@@ -943,27 +905,20 @@
943
  }
944
 
945
  // complete
946
- if ( currentProgress >= 100 ) {
947
  clearInterval( timerId );
948
- }
949
  }, 300 );
950
  },
951
- change: function ( event, ui ) {
952
- // console.log( event );
953
-
954
  progressLabel.text( progressbar.progressbar( 'value' ) + '%' );
955
  },
956
- complete: function ( event, ui ) {
957
- // console.log( event );
958
-
959
- setTimeout( function () {
960
  if ( cnWelcomeArgs.complianceStatus )
961
  $( '.cn-compliance-check' ).find( '.cn-compliance-feedback' ).html( '<p class="cn-message">' + cnWelcomeArgs.compliancePassed + '</p>' ).removeClass( 'cn-hidden' );
962
  else
963
  $( '.cn-compliance-check' ).find( '.cn-compliance-feedback' ).html( '<p class="cn-error">' + cnWelcomeArgs.complianceFailed + '</p>' ).removeClass( 'cn-hidden' );
964
  }, 500 );
965
-
966
- // $( progressbar ).progressbar( "destroy" );
967
  }
968
  } );
969
 
@@ -973,16 +928,14 @@
973
  }
974
  }
975
 
976
- $( document ).on( 'click', '.cn-run-upgrade, .cn-run-welcome', function ( e ) {
977
  e.preventDefault();
978
 
979
- // console.log( e );
980
-
981
  // modal
982
  initModal();
983
  } );
984
 
985
- $( document ).ready( function () {
986
  var welcome = false;
987
 
988
  welcome = cnGetUrlParam( 'welcome' );
@@ -993,7 +946,7 @@
993
  }
994
  } );
995
 
996
- $( document ).on( 'click', '.cn-sign-up', function ( e ) {
997
  e.preventDefault();
998
 
999
  $( '.cn-screen-button' ).trigger( 'click' );
@@ -1008,10 +961,10 @@
1008
  for ( i = 0; i < urlVars.length; i ++ ) {
1009
  parameterName = urlVars[i].split( '=' );
1010
 
1011
- if ( parameterName[0] === parameter ) {
1012
  return typeof parameterName[1] === undefined ? true : decodeURIComponent( parameterName[1] );
1013
- }
1014
  }
 
1015
  return false;
1016
  };
1017
 
1
+ ( function( $ ) {
2
 
3
  // ready event
4
+ $( function() {
5
  var btClient = false;
6
  var btCreditCardsInitialized = false;
7
  var btPayPalInitialized = false;
8
 
9
+ var btInit = function() {
10
  var result = btInitToken();
11
 
12
  if ( result !== false && btCreditCardsInitialized === false ) {
13
+ // ajax was successful
14
+ result.done( function( response ) {
15
  // token received
16
  try {
17
  // parse response
27
  } catch ( e ) {
28
  btGatewayFail( 'btInit catch' );
29
  }
30
+ // ajax failed
31
+ } ).fail( function() {
32
  btGatewayFail( 'btInit AJAX failed' );
33
  } );
34
  }
35
  }
36
 
37
+ var btInitToken = function() {
38
  // payment screen?
39
  var paymentEl = $( '.cn-sidebar form[data-action="payment"]' );
40
 
43
  paymentEl.addClass( 'cn-form-disabled' );
44
 
45
  if ( typeof braintree !== 'undefined' ) {
46
+ var ajaxArgs = {
47
+ action: 'cn_api_request',
48
+ request: 'get_bt_init_token',
49
+ nonce: cnWelcomeArgs.nonce
50
+ };
51
+
52
+ // network area?
53
+ if ( cnWelcomeArgs.network === '1' )
54
+ ajaxArgs.cn_network = 1;
55
+
56
  return $.ajax( {
57
  url: cnWelcomeArgs.ajaxURL,
58
  type: 'POST',
59
  dataType: 'html',
60
+ data: ajaxArgs
 
 
 
 
61
  } );
62
  } else
63
  return false;
65
  return false;
66
  }
67
 
68
+ var btInitPaymentMethod = function( type ) {
 
 
69
  if ( btClient !== false ) {
70
  if ( type === 'credit_card' && btCreditCardsInitialized === false ) {
71
  $( 'form.cn-form[data-action="payment"]' ).addClass( 'cn-form-disabled' );
80
  btGatewayFail( 'btInitPaymentMethod btClient is false' );
81
  }
82
 
83
+ var btCreditCardsInit = function( clientInstance ) {
 
 
84
  return braintree.hostedFields.create( {
85
  client: clientInstance,
86
  styles: {
113
  } );
114
  }
115
 
116
+ var btHostedFieldsInstance = function( hostedFieldsInstance ) {
 
 
117
  btCreditCardsInitialized = true;
118
 
119
  var form = $( 'form.cn-form[data-action="payment"]' );
120
 
121
  form.removeClass( 'cn-form-disabled' );
122
 
123
+ form.on( 'submit', function() {
124
  if ( form.hasClass( 'cn-payment-in-progress' ) )
125
  return false;
126
 
134
  var state = hostedFieldsInstance.getState();
135
 
136
  // check hosted fields
137
+ Object.keys( state.fields ).forEach( function( field ) {
138
  if ( ! state.fields[field].isValid ) {
139
  $( state.fields[field].container ).addClass( 'braintree-hosted-fields-invalid' );
140
 
143
  } );
144
 
145
  if ( invalidForm ) {
146
+ setTimeout( function() {
147
  cnDisplayError( cnWelcomeArgs.invalidFields, form );
148
 
149
  // spin the spinner, if exists
154
  return false;
155
  }
156
 
157
+ hostedFieldsInstance.tokenize( function( err, payload ) {
 
 
 
 
158
  if ( err ) {
159
  cnDisplayError( cnWelcomeArgs.error );
160
 
172
  } );
173
  }
174
 
175
+ var btPaypalCheckoutInit = function( clientInstance ) {
 
 
176
  return braintree.paypalCheckout.create( {
177
  client: clientInstance
178
  } );
179
  }
180
 
181
+ var btPaypalCheckoutSDK = function( paypalCheckoutInstance ) {
 
 
182
  return paypalCheckoutInstance.loadPayPalSDK( {
183
  vault: true,
184
  intent: 'tokenize'
185
  } );
186
  }
187
 
188
+ var btPaypalCheckoutInstance = function( paypalCheckoutInstance ) {
 
 
189
  var form = $( 'form.cn-form[data-action="payment"]' );
190
 
191
  return paypal.Buttons( {
192
  fundingSource: paypal.FUNDING.PAYPAL,
193
+ createBillingAgreement: function() {
 
 
194
  form.addClass( 'cn-form-disabled' );
195
 
196
  return paypalCheckoutInstance.createPayment( {
199
  currency: 'EUR'
200
  } );
201
  },
202
+ onApprove: function( data, actions ) {
203
+ return paypalCheckoutInstance.tokenizePayment( data ).then( function( payload ) {
 
 
 
 
 
 
204
  form.addClass( 'cn-payment-in-progress' );
205
  form.find( 'input[name="payment_nonce"]' ).val( payload.nonce );
206
  form.find( 'input[name="cn_payment_identifier"]' ).val( payload.details.email );
207
 
 
 
 
208
  $( '#cn_submit_pro' ).find( '.cn-screen-button[data-screen="4"]' ).trigger( 'click' );
209
  } );
210
  },
211
+ onCancel: function( data ) {
 
 
212
  form.removeClass( 'cn-form-disabled' );
213
  },
214
+ onError: function( err ) {
 
 
215
  form.removeClass( 'cn-form-disabled' );
216
  }
217
  } ).render( '#cn_paypal_button' );
218
  }
219
 
220
+ var btPaypalCheckoutButton = function() {
 
 
221
  btPayPalInitialized = true;
222
 
223
  $( 'form.cn-form[data-action="payment"]' ).removeClass( 'cn-form-disabled' );
224
  }
225
 
226
+ var btGatewayFail = function( error ) {
 
 
227
  if ( typeof error !== 'undefined' )
228
  console.log( error );
229
 
230
  cnDisplayError( cnWelcomeArgs.error );
231
  }
232
 
233
+ var cnDisplayError = function( message, form ) {
234
  if ( typeof form === 'undefined' )
235
  form = $( 'form.cn-form[data-action="payment"]' );
236
 
237
  form.find( '.cn-form-feedback' ).html( '<p class="cn-error">' + message + '</p>' ).removeClass( 'cn-hidden' );
238
  }
239
 
240
+ var cnWelcomeScreen = function( target ) {
241
  var screen = $( target ).data( 'screen' );
242
  var steps = [1, 2, 3, 4];
243
  var sidebars = ['login', 'register', 'configure', 'payment'];
248
  nonce: cnWelcomeArgs.nonce
249
  };
250
 
251
+ if ( $.inArray( screen, steps ) !== -1 ) {
252
  var container = $( '.cn-welcome-wrap' );
253
 
254
  requestData.screen = screen;
255
+ } else if ( $.inArray( screen, sidebars ) !== -1 ) {
256
  var container = $( '.cn-sidebar' );
257
 
258
  requestData.screen = screen;
259
  } else
260
  return false;
261
 
262
+ // network area?
263
+ if ( cnWelcomeArgs.network === '1' )
264
+ requestData.cn_network = 1;
265
+
266
  // add loading overlay
267
  $( container ).addClass( 'cn-loading' );
268
 
271
  type: 'POST',
272
  dataType: 'html',
273
  data: requestData
274
+ } ).done( function( response ) {
275
  $( container ).replaceWith( response );
276
+ } ).fail( function( jqXHR, textStatus, errorThrown ) {
277
  //
278
+ } ).always( function( response ) {
279
  // remove spinner
280
  $( container ).removeClass( 'cn-loading' );
281
 
288
  return this;
289
  };
290
 
291
+ var cnWelcomeForm = function( form ) {
292
  var formAction = $( form[0] ).data( 'action' );
293
  var formResult = null;
294
  var formData = {
303
  formData.request = formAction;
304
 
305
  // convert form data to object
306
+ $( form[0] ).serializeArray().map( function( x ) {
307
  // exception for checkboxes
308
  if ( x.name === 'cn_laws' ) {
309
  var arrayVal = typeof formData[x.name] !== 'undefined' ? formData[x.name] : [];
311
  arrayVal.push( x.value );
312
 
313
  formData[x.name] = arrayVal;
314
+ } else
315
  formData[x.name] = x.value;
 
316
  } );
317
 
318
+ // network area?
319
+ if ( cnWelcomeArgs.network === '1' )
320
+ formData.cn_network = 1;
321
+
322
  formResult = $.ajax( {
323
  url: cnWelcomeArgs.ajaxURL,
324
  type: 'POST',
330
  };
331
 
332
  // handle screen loading
333
+ $( document ).on( 'click', '.cn-screen-button', function( e ) {
334
  var form = $( e.target ).closest( 'form' );
335
  var result = false;
336
 
347
  var formAction = formDataset.hasOwnProperty( 'action' ) ? formDataset.action : '';
348
 
349
  // get form data
350
+ $( form[0] ).serializeArray().map( function( x ) {
351
  // exception for checkboxes
352
  if ( x.name === 'cn_laws' ) {
353
  var arrayVal = typeof formData[x.name] !== 'undefined' ? formData[x.name] : [];
355
  arrayVal.push( x.value );
356
 
357
  formData[x.name] = arrayVal;
358
+ } else
359
  formData[x.name] = x.value;
 
360
  } );
361
 
362
  // payment?
363
  if ( formAction === 'payment' ) {
 
364
  // free
365
  if ( formData.plan === 'free' ) {
366
  // load screen
375
  // disable form
376
  if ( paymentEl.length )
377
  paymentEl.addClass( 'cn-form-disabled' );
378
+
379
  // get subscription ID
380
  var subscriptionID = formData.hasOwnProperty( 'cn_subscription_id' ) ? parseInt( formData.cn_subscription_id ) : 0;
381
 
382
+ var ajaxArgs = {
383
+ action: 'cn_api_request',
384
+ request: 'use_license',
385
+ subscriptionID: subscriptionID,
386
+ nonce: cnWelcomeArgs.nonce
387
+ };
388
+
389
+ // network area?
390
+ if ( cnWelcomeArgs.network === '1' )
391
+ ajaxArgs.cn_network = 1;
392
+
393
  // assign license request
394
  result = $.ajax( {
395
  url: cnWelcomeArgs.ajaxURL,
396
  type: 'POST',
397
  dataType: 'json',
398
+ data: ajaxArgs
 
 
 
 
 
399
  } );
400
+
401
  // process license
402
+ result.done( function( response ) {
403
  // error
404
  if ( response.hasOwnProperty( 'error' ) ) {
405
  cnDisplayError( response.error, $( form[0] ) );
 
 
406
 
407
  return false;
408
  // message
415
  return result;
416
  }
417
  } );
418
+
419
  // remove spinner
420
+ result.always( function( response ) {
421
  if ( $( e.target ).find( '.cn-spinner' ).length )
422
  $( e.target ).find( '.cn-spinner' ).removeClass( 'spin' );
423
+
424
  // enable form
425
  if ( paymentEl.length )
426
  paymentEl.removeClass( 'cn-form-disabled' );
427
  } );
 
428
  // pro
429
  } else {
430
  // only credit cards
434
  return false;
435
  }
436
  }
 
437
  // other forms
438
  } else
439
  e.preventDefault();
440
+
441
  // break here on license payment
442
  if ( formAction === 'payment' && formData.plan === 'license' )
443
  return result;
445
  // get form and process it
446
  result = cnWelcomeForm( form );
447
 
448
+ result.done( function( response ) {
449
  // error
450
  if ( response.hasOwnProperty( 'error' ) ) {
451
  cnDisplayError( response.error, $( form[0] ) );
452
 
453
  return false;
454
+ // message
455
  } else if ( response.hasOwnProperty( 'message' ) ) {
456
  cnDisplayError( response.message, $( form[0] ) );
457
 
458
  return false;
459
+ // all good
460
  } else {
461
  switch ( formAction ) {
462
  // logged in, go to success or billing
463
+ case 'login':
464
  // register complete, go to success or billing
465
+ case 'register':
 
466
  // if there are any subscriptions
467
  if ( response.hasOwnProperty( 'subscriptions' ) ) {
468
  var subscriptions = response.subscriptions;
507
 
508
  // init braintree after payment screen is loaded via AJAX
509
  btInit();
 
510
  break;
511
 
512
+ case 'configure':
513
+ default:
514
  // load screen
515
  cnWelcomeScreen( e.target );
516
  break;
518
  }
519
  } );
520
 
521
+ result.always( function( response ) {
522
  if ( $( e.target ).find( '.cn-spinner' ).length )
523
  $( e.target ).find( '.cn-spinner' ).removeClass( 'spin' );
524
 
533
  } );
534
 
535
  //
536
+ $( document ).on( 'screen-loaded', function() {
537
  var configureFields = $( '#cn-form-configure' ).serializeArray() || [];
538
  var frame = window.frames[ 'cn_iframe_id' ];
539
 
540
  if ( configureFields.length > 0 ) {
541
+ $( configureFields ).each( function( index, field ) {
542
  } );
543
  }
544
  } );
545
 
546
  // change payment method
547
+ $( document ).on( 'change', 'input[name="method"]', function() {
548
  var input = $( this );
549
 
550
  $( '#cn_payment_method_credit_card, #cn_payment_method_paypal' ).toggle();
555
  btInitPaymentMethod( input.val() );
556
  } );
557
 
558
+ //
559
+ $( document ).on( 'click', '.cn-accordion > .cn-accordion-item .cn-accordion-button', function() {
560
  var accordionItem = $( this ).closest( '.cn-accordion-item' );
561
  var activeItem = $( this ).closest( '.cn-accordion' ).find( '.cn-accordion-item:not(.cn-collapsed)' );
562
 
569
  } );
570
 
571
  // live preview
572
+ $( document ).on( 'change', 'input[name="cn_position"]', function() {
573
  var val = $( this ).val();
574
  var frame = window.frames['cn_iframe_id'];
575
 
576
  frame.contentWindow.postMessage( {call: 'position', value: val} );
577
  } );
578
 
579
+ $( document ).on( 'change', 'input[name="cn_laws"]', function() {
580
  var val = [];
581
 
582
+ $( 'input[name="cn_laws"]:checked' ).each( function() {
583
  val.push( $( this ).val() );
584
  } );
585
 
588
  frame.contentWindow.postMessage( {call: 'laws', value: val} );
589
  } );
590
 
591
+ $( document ).on( 'change', 'input[name="cn_naming"]', function() {
592
  var val = [];
593
 
594
+ $( 'input[name="cn_naming"]:checked' ).each( function() {
595
  val.push( $( this ).val() );
596
  } );
597
 
600
  frame.contentWindow.postMessage( {call: 'naming', value: val} );
601
  } );
602
 
603
+ $( document ).on( 'change', 'input[name="cn_privacy_paper"]', function() {
604
  var val = $( this ).prop( 'checked' );
605
  var frame = window.frames['cn_iframe_id'];
606
 
607
  frame.contentWindow.postMessage( {call: 'privacy_paper', value: val} );
608
  } );
609
 
610
+ $( document ).on( 'change', 'input[name="cn_privacy_contact"]', function() {
611
  var val = $( this ).prop( 'checked' );
612
  var frame = window.frames['cn_iframe_id'];
613
 
614
  frame.contentWindow.postMessage( {call: 'privacy_contact', value: val} );
615
  } );
616
 
617
+ $( document ).on( 'change', 'input[name="cn_color_primary"]', function() {
618
  var val = $( this ).val();
619
  var frame = window.frames['cn_iframe_id'];
620
 
621
  frame.contentWindow.postMessage( {call: 'color_primary', value: val} );
622
  } );
623
 
624
+ $( document ).on( 'change', 'input[name="cn_color_background"]', function() {
625
  var val = $( this ).val();
626
  var frame = window.frames['cn_iframe_id'];
627
 
628
  frame.contentWindow.postMessage( {call: 'color_background', value: val} );
629
  } );
630
 
631
+ $( document ).on( 'change', 'input[name="cn_color_border"]', function() {
632
  var val = $( this ).val();
633
  var frame = window.frames['cn_iframe_id'];
634
 
635
  frame.contentWindow.postMessage( {call: 'color_border', value: val} );
636
  } );
637
 
638
+ $( document ).on( 'change', 'input[name="cn_color_text"]', function() {
639
  var val = $( this ).val();
640
  var frame = window.frames['cn_iframe_id'];
641
 
642
  frame.contentWindow.postMessage( {call: 'color_text', value: val} );
643
  } );
644
 
645
+ $( document ).on( 'change', 'input[name="cn_color_heading"]', function() {
646
  var val = $( this ).val();
647
  var frame = window.frames['cn_iframe_id'];
648
 
649
  frame.contentWindow.postMessage( {call: 'color_heading', value: val} );
650
  } );
651
 
652
+ $( document ).on( 'change', 'input[name="cn_color_button_text"]', function() {
653
  var val = $( this ).val();
654
  var frame = window.frames['cn_iframe_id'];
655
 
657
  } );
658
 
659
  // handle monthly / yearly payment plan
660
+ $( document ).on( 'change', 'input[name="cn_pricing_type"]', function() {
661
  // pricing plans
662
  var plansMonthly = cnWelcomeArgs.pricingMonthly;
663
  var plansYearly = cnWelcomeArgs.pricingYearly;
668
  var names = Object.keys( checked === 'yearly' ? plansYearly : plansMonthly );
669
  var pricing = Object.values( checked === 'yearly' ? plansYearly : plansMonthly );
670
 
671
+ if ( checked === 'yearly' )
672
  $( '.cn-plan-period' ).text( cnWelcomeArgs.paidYear );
673
+ else
674
  $( '.cn-plan-period' ).text( cnWelcomeArgs.paidMonth );
 
675
 
676
  // replace options
677
  var i = 0;
679
  for ( var property in pricing ) {
680
  var option = pricingOptions[i];
681
 
 
 
682
  $( option ).val( names[i] );
683
  $( option ).attr( 'data-price', pricing[i] );
684
+ i++;
685
  }
686
 
687
  // trigger plan selection
688
  $( 'select[name="cn_pricing_plan"]' ).trigger( 'change' );
 
689
  } );
690
 
691
  // handle pro plan selection
692
+ $( document ).on( 'change', 'select[name="cn_pricing_plan"]', function() {
693
  var el = $( '#cn-pricing-plans' );
694
  var selected = $( el ).find( 'option:selected' );
695
 
702
  availablePlans = availablePlans.concat( Object.keys( cnWelcomeArgs.pricingMonthly ) );
703
  availablePlans = availablePlans.concat( Object.keys( cnWelcomeArgs.pricingYearly ) );
704
 
705
+ var input = $( this );
706
+ var inputVal = input.val();
 
 
707
 
708
+ inputVal = availablePlans.indexOf( inputVal ) !== -1 ? inputVal : 'free';
709
 
710
  if ( inputVal === 'free' ) {
711
  $( '#cn_submit_free' ).removeClass( 'cn-hidden' );
723
  } );
724
 
725
  // handle free / pro / license selection
726
+ $( document ).on( 'change', 'input[name="plan"]', function() {
727
  var input = $( this ),
728
  inputVal = input.val();
729
 
750
  } );
751
 
752
  // highlight form
753
+ $( document ).on( 'click', 'input[name="cn_pricing"]', function() {
754
  $( '.cn-accordion .cn-accordion-item:first-child:not(.cn-collapsed)' ).focus();
755
  } );
756
 
757
  // select plan payment
758
+ $( document ).on( 'change', 'input[name="cn_pricing"]', function() {
759
  var input = $( this ),
760
  inputVal = input.val();
761
 
782
 
783
  } );
784
 
785
+ $( document ).on( 'ajaxComplete', function() {
786
  // color picker
787
  initSpectrum();
788
  } );
802
  modal = $( "#cn-modal-trigger" );
803
 
804
  if ( modal ) {
 
805
  $( "#cn-modal-trigger" ).modaal( {
806
  content_source: cnWelcomeArgs.ajaxURL + '?action=cn_welcome_screen' + '&nonce=' + cnWelcomeArgs.nonce + '&screen=1',
807
  type: 'ajax',
808
  width: 1600,
809
  custom_class: 'cn-modal',
810
  // is_locked: true
811
+ ajax_success: function() {
812
  progressbar = $( document ).find( '.cn-progressbar' );
813
 
814
  if ( progressbar ) {
815
  timerId = initProgressBar( progressbar );
816
  }
817
  },
818
+ before_close: function() {
819
  clearInterval( timerId );
820
 
821
  var currentStep = $( '.cn-welcome-wrap' );
826
  window.location.reload( true );
827
  }
828
  },
829
+ after_close: function() {
830
  progressbar = $( document ).find( '.cn-progressbar' );
831
 
832
  $( progressbar ).progressbar( "destroy" );
835
 
836
  $( modal ).trigger( 'click' );
837
 
838
+ $( document ).on( 'click', '.cn-skip-button', function( e ) {
839
  $( '#modaal-close' ).trigger( 'click' );
840
  } );
841
  }
849
  timerId;
850
 
851
  if ( progressbar ) {
852
+ $( document ).on( 'click', '.cn-screen-button', function( e ) {
 
853
  e.preventDefault();
854
 
 
 
855
  clearInterval( timerId );
856
  } );
857
 
858
  $( progressbar ).progressbar( {
859
  value: 5,
860
  max: 100,
861
+ create: function( event, ui ) {
862
+ timerId = setInterval( function() {
 
 
863
  // increment progress bar
864
  currentProgress += 5;
865
 
 
 
866
  // update progressbar
867
  progressbar.progressbar( 'value', currentProgress );
868
 
905
  }
906
 
907
  // complete
908
+ if ( currentProgress >= 100 )
909
  clearInterval( timerId );
 
910
  }, 300 );
911
  },
912
+ change: function( event, ui ) {
 
 
913
  progressLabel.text( progressbar.progressbar( 'value' ) + '%' );
914
  },
915
+ complete: function( event, ui ) {
916
+ setTimeout( function() {
 
 
917
  if ( cnWelcomeArgs.complianceStatus )
918
  $( '.cn-compliance-check' ).find( '.cn-compliance-feedback' ).html( '<p class="cn-message">' + cnWelcomeArgs.compliancePassed + '</p>' ).removeClass( 'cn-hidden' );
919
  else
920
  $( '.cn-compliance-check' ).find( '.cn-compliance-feedback' ).html( '<p class="cn-error">' + cnWelcomeArgs.complianceFailed + '</p>' ).removeClass( 'cn-hidden' );
921
  }, 500 );
 
 
922
  }
923
  } );
924
 
928
  }
929
  }
930
 
931
+ $( document ).on( 'click', '.cn-run-upgrade, .cn-run-welcome', function( e ) {
932
  e.preventDefault();
933
 
 
 
934
  // modal
935
  initModal();
936
  } );
937
 
938
+ $( document ).ready( function() {
939
  var welcome = false;
940
 
941
  welcome = cnGetUrlParam( 'welcome' );
946
  }
947
  } );
948
 
949
+ $( document ).on( 'click', '.cn-sign-up', function( e ) {
950
  e.preventDefault();
951
 
952
  $( '.cn-screen-button' ).trigger( 'click' );
961
  for ( i = 0; i < urlVars.length; i ++ ) {
962
  parameterName = urlVars[i].split( '=' );
963
 
964
+ if ( parameterName[0] === parameter )
965
  return typeof parameterName[1] === undefined ? true : decodeURIComponent( parameterName[1] );
 
966
  }
967
+
968
  return false;
969
  };
970
 
js/admin.js CHANGED
@@ -4,31 +4,41 @@
4
  $( function() {
5
  // initialize color picker
6
  $( '.cn_color' ).wpColorPicker();
7
-
 
8
  $( '#cn_app_purge_cache a' ).on( 'click', function( e ) {
9
  e.preventDefault();
10
-
11
  var el = this;
12
-
13
  $( el ).parent().addClass( 'loading' ).append( '<span class="spinner is-active" style="float: none;"></span>' );
14
-
 
 
 
 
 
 
 
 
 
15
  $.ajax( {
16
  url: cnArgs.ajaxURL,
17
  type: 'POST',
18
  dataType: 'json',
19
- data: {
20
- action: 'cn_purge_cache',
21
- nonce: cnArgs.nonce
22
- }
23
- } )
24
- .done ( function ( result ) {
25
  console.log( result );
26
- } )
27
- .always ( function ( result ) {
28
  $( el ).parent().find( '.spinner' ).remove();
29
  } );
30
  } );
31
 
 
 
 
 
 
32
  // refuse option
33
  $( '#cn_refuse_opt' ).on( 'change', function() {
34
  if ( $( this ).is( ':checked' ) )
@@ -36,7 +46,7 @@
36
  else
37
  $( '#cn_refuse_opt_container' ).slideUp( 'fast' );
38
  } );
39
-
40
  // revoke option
41
  $( '#cn_revoke_cookies' ).on( 'change', function() {
42
  if ( $( this ).is( ':checked' ) )
@@ -73,7 +83,8 @@
73
  } );
74
  }
75
  } );
76
-
 
77
  $( '#cn_refuse_code_fields' ).find( 'a' ).on( 'click', function( e ) {
78
  e.preventDefault();
79
 
4
  $( function() {
5
  // initialize color picker
6
  $( '.cn_color' ).wpColorPicker();
7
+
8
+ // purge cache
9
  $( '#cn_app_purge_cache a' ).on( 'click', function( e ) {
10
  e.preventDefault();
11
+
12
  var el = this;
13
+
14
  $( el ).parent().addClass( 'loading' ).append( '<span class="spinner is-active" style="float: none;"></span>' );
15
+
16
+ var ajaxArgs = {
17
+ action: 'cn_purge_cache',
18
+ nonce: cnArgs.nonce
19
+ };
20
+
21
+ // network area?
22
+ if ( cnArgs.network === '1' )
23
+ ajaxArgs.cn_network = 1;
24
+
25
  $.ajax( {
26
  url: cnArgs.ajaxURL,
27
  type: 'POST',
28
  dataType: 'json',
29
+ data: ajaxArgs
30
+ } ).done( function( result ) {
 
 
 
 
31
  console.log( result );
32
+ } ).always( function( result ) {
 
33
  $( el ).parent().find( '.spinner' ).remove();
34
  } );
35
  } );
36
 
37
+ // global override
38
+ $( 'input[name="cookie_notice_options[global_override]"]' ).on( 'change', function() {
39
+ $( '.cookie-notice-settings form' ).toggleClass( 'cn-options-disabled' );
40
+ } );
41
+
42
  // refuse option
43
  $( '#cn_refuse_opt' ).on( 'change', function() {
44
  if ( $( this ).is( ':checked' ) )
46
  else
47
  $( '#cn_refuse_opt_container' ).slideUp( 'fast' );
48
  } );
49
+
50
  // revoke option
51
  $( '#cn_revoke_cookies' ).on( 'change', function() {
52
  if ( $( this ).is( ':checked' ) )
83
  } );
84
  }
85
  } );
86
+
87
+ // script blocking
88
  $( '#cn_refuse_code_fields' ).find( 'a' ).on( 'click', function( e ) {
89
  e.preventDefault();
90
 
js/admin.min.js CHANGED
@@ -1,5 +1 @@
1
- (function($){$(function(){$('.cn_color').wpColorPicker();$('#cn_app_purge_cache a').on('click',function(e){e.preventDefault();var el=this;$(el).parent().addClass('loading').append('<span class="spinner is-active" style="float: none;"></span>');$.ajax({url:cnArgs.ajaxURL,type:'POST',dataType:'json',data:{action:'cn_purge_cache',nonce:cnArgs.nonce}}).done(function(result){console.log(result)}).always(function(result){$(el).parent().find('.spinner').remove()})});$('#cn_refuse_opt').on('change',function(){if($(this).is(':checked'))
2
- $('#cn_refuse_opt_container').slideDown('fast');else $('#cn_refuse_opt_container').slideUp('fast')});$('#cn_revoke_cookies').on('change',function(){if($(this).is(':checked'))
3
- $('#cn_revoke_opt_container').slideDown('fast');else $('#cn_revoke_opt_container').slideUp('fast')});$('#cn_see_more').on('change',function(){if($(this).is(':checked'))
4
- $('#cn_see_more_opt').slideDown('fast');else $('#cn_see_more_opt').slideUp('fast')});$('#cn_on_scroll').on('change',function(){if($(this).is(':checked'))
5
- $('#cn_on_scroll_offset').slideDown('fast');else $('#cn_on_scroll_offset').slideUp('fast')});$('#cn_see_more_link-custom, #cn_see_more_link-page').on('change',function(){if($('#cn_see_more_link-custom:checked').val()==='custom'){$('#cn_see_more_opt_page').slideUp('fast',function(){$('#cn_see_more_opt_link').slideDown('fast')})}else if($('#cn_see_more_link-page:checked').val()==='page'){$('#cn_see_more_opt_link').slideUp('fast',function(){$('#cn_see_more_opt_page').slideDown('fast')})}});$('#cn_refuse_code_fields').find('a').on('click',function(e){e.preventDefault();$('#cn_refuse_code_fields').find('a').removeClass('nav-tab-active');$('.refuse-code-tab').removeClass('active');var id=$(this).attr('id').replace('-tab','');$('#'+id).addClass('active');$(this).addClass('nav-tab-active')})});$(document).on('click','input#reset_cookie_notice_options',function(){return confirm(cnArgs.resetToDefaults)})})(jQuery)
1
+ !function($){$(function(){$(".cn_color").wpColorPicker(),$("#cn_app_purge_cache a").on("click",function(b){b.preventDefault();var c=this;$(c).parent().addClass("loading").append('<span class="spinner is-active" style="float: none;"></span>');var a={action:"cn_purge_cache",nonce:cnArgs.nonce};"1"===cnArgs.network&&(a.cn_network=1),$.ajax({url:cnArgs.ajaxURL,type:"POST",dataType:"json",data:a}).done(function(a){console.log(a)}).always(function(a){$(c).parent().find(".spinner").remove()})}),$('input[name="cookie_notice_options[global_override]"]').on("change",function(){$(".cookie-notice-settings form").toggleClass("cn-options-disabled")}),$("#cn_refuse_opt").on("change",function(){$(this).is(":checked")?$("#cn_refuse_opt_container").slideDown("fast"):$("#cn_refuse_opt_container").slideUp("fast")}),$("#cn_revoke_cookies").on("change",function(){$(this).is(":checked")?$("#cn_revoke_opt_container").slideDown("fast"):$("#cn_revoke_opt_container").slideUp("fast")}),$("#cn_see_more").on("change",function(){$(this).is(":checked")?$("#cn_see_more_opt").slideDown("fast"):$("#cn_see_more_opt").slideUp("fast")}),$("#cn_on_scroll").on("change",function(){$(this).is(":checked")?$("#cn_on_scroll_offset").slideDown("fast"):$("#cn_on_scroll_offset").slideUp("fast")}),$("#cn_see_more_link-custom, #cn_see_more_link-page").on("change",function(){"custom"===$("#cn_see_more_link-custom:checked").val()?$("#cn_see_more_opt_page").slideUp("fast",function(){$("#cn_see_more_opt_link").slideDown("fast")}):"page"===$("#cn_see_more_link-page:checked").val()&&$("#cn_see_more_opt_link").slideUp("fast",function(){$("#cn_see_more_opt_page").slideDown("fast")})}),$("#cn_refuse_code_fields").find("a").on("click",function(a){a.preventDefault(),$("#cn_refuse_code_fields").find("a").removeClass("nav-tab-active"),$(".refuse-code-tab").removeClass("active");var b=$(this).attr("id").replace("-tab","");$("#"+b).addClass("active"),$(this).addClass("nav-tab-active")})}),$(document).on("click","input#reset_cookie_notice_options",function(){return confirm(cnArgs.resetToDefaults)})}(jQuery)
 
 
 
 
js/front-welcome.js CHANGED
@@ -1,461 +1,454 @@
1
- ( function( $ ) {
2
-
3
- // ready event
4
- $( function() {
5
- var cnHiddenElements = {};
6
-
7
- // listen for the load
8
- document.addEventListener( 'load.hu', function( e ) {
9
- // set widget text strings
10
- hu.setTexts( cnFrontWelcome.textStrings );
11
- } );
12
-
13
- // listen for the reload
14
- document.addEventListener( 'reload.hu', function( e ) {
15
- var container = $( '#hu' );
16
- var customOptions = { config: {
17
- dontSellLink: true,
18
- privacyPolicyLink: true,
19
- privacyPaper: true,
20
- privacyContact: true
21
- } };
22
-
23
- // set widget options
24
- hu.setOptions( customOptions );
25
- } );
26
-
27
- // listen for the display
28
- document.addEventListener( 'display.hu', function( e ) {
29
- var val = [],
30
- container = $( '#hu' );
31
-
32
- var customOptions = { config: {
33
- // make it empty
34
- } };
35
-
36
- $( parent.document ).find( 'input[name="cn_laws"]:checked' ).each( function() {
37
- val.push( $( this ).val() );
38
- } );
39
-
40
- // hide paper and contact
41
- if ( $( parent.document ).find( 'input[name="cn_privacy_paper"]' ).prop( 'checked' ) === true ) {
42
- $( container ).find( '#hu-cookies-paper' ).show();
43
-
44
- } else {
45
- $( container ).find( '#hu-cookies-paper' ).hide();
46
- }
47
-
48
- if ( $( parent.document ).find( 'input[name="cn_privacy_contact"]' ).prop( 'checked' ) === true ) {
49
- $( container ).find( '#hu-cookies-contact' ).show();
50
- } else {
51
- $( container ).find( '#hu-cookies-contact' ).hide();
52
- }
53
-
54
- if ( $.inArray( 'ccpa', val ) !== -1 ) {
55
- var htmlElement = $( $( container ).find( '#hu-cookies-notice-dontsell-btn' ) );
56
-
57
- if ( htmlElement.length === 0 ) {
58
- $( '#hu-policy-links' ).append( cnHiddenElements.ccpa );
59
-
60
- delete cnHiddenElements.ccpa;
61
- }
62
-
63
- $.extend( customOptions.config, { dontSellLink: true } );
64
- } else {
65
- var htmlElement = $( $( container ).find( '#hu-cookies-notice-dontsell-btn' ) );
66
-
67
- // add to hidden elements
68
- if ( htmlElement ) {
69
- cnHiddenElements['ccpa'] = htmlElement;
70
-
71
- // remove el
72
- $( htmlElement ).remove();
73
- }
74
-
75
- $.extend( customOptions.config, { dontSellLink: false } );
76
- }
77
-
78
- if ( $.inArray( 'gdpr', val ) !== -1 ) {
79
- var htmlElement = $( $( container ).find( '#hu-cookies-notice-privacy-btn' ) );
80
-
81
- if ( htmlElement.length === 0 ) {
82
- $( '#hu-policy-links' ).prepend( cnHiddenElements.gdpr );
83
-
84
- delete cnHiddenElements.gdpr;
85
- }
86
-
87
- $.extend( customOptions.config, { privacyPolicyLink: true } );
88
- } else {
89
- var htmlElement = $( $( container ).find( '#hu-cookies-notice-privacy-btn' ) );
90
-
91
- // add to hidden elements
92
- if ( htmlElement ) {
93
- cnHiddenElements['gdpr'] = htmlElement;
94
-
95
- // remove el
96
- $( htmlElement ).remove();
97
- }
98
-
99
- $.extend( customOptions.config, { privacyPolicyLink: false } );
100
- }
101
-
102
- // console.log( customOptions );
103
-
104
- // set widget options
105
- hu.setOptions( customOptions );
106
- } );
107
-
108
- // listen for the parent
109
- window.addEventListener( 'message', function( event ) {
110
- var iframe = $( parent.document ).find( '#cn_iframe_id' ),
111
- form = $( parent.document ).find( '#cn-form-configure' );
112
-
113
- // console.log( iframe );
114
-
115
- // add spinner
116
- $( iframe ).closest( '.has-loader' ).addClass( 'cn-loading' ).append( '<span class="cn-spinner"></span>' );
117
- // lock options
118
- $( form ).addClass( 'cn-form-disabled' );
119
-
120
- // emit loader
121
- window.setTimeout( function() {
122
- if ( typeof event.data == 'object' ) {
123
- var container = $( '#hu' ),
124
- option = event.data.call,
125
- customOptions = {},
126
- customTexts = {};
127
-
128
- // console.log( option );
129
-
130
- switch ( option ) {
131
-
132
- case 'position':
133
- $( container ).removeClass( 'hu-position-bottom hu-position-top hu-position-left hu-position-right hu-position-center' );
134
- $( container ).addClass( 'hu-position-' + event.data.value );
135
-
136
- customOptions = { design: { position: event.data.value } }
137
- break;
138
-
139
- case 'naming':
140
- var level1 = $( '.hu-cookies-notice-consent-choices-1' ),
141
- level2 = $( '.hu-cookies-notice-consent-choices-2' ),
142
- level3 = $( '.hu-cookies-notice-consent-choices-3' );
143
-
144
- var text1 = cnFrontWelcome.levelNames[event.data.value][1],
145
- text2 = cnFrontWelcome.levelNames[event.data.value][2],
146
- text3 = cnFrontWelcome.levelNames[event.data.value][3];
147
-
148
- // apply text to dom elements
149
- $( level1 ).find( '.hu-toggle-label' ).text( text1 );
150
- $( level2 ).find( '.hu-toggle-label' ).text( text2 );
151
- $( level3 ).find( '.hu-toggle-label' ).text( text3 );
152
-
153
- // apply text to text strings
154
- customTexts = {
155
- levelNameText_1: text1,
156
- levelNameText_2: text2,
157
- levelNameText_3: text3
158
- }
159
- break;
160
-
161
- case 'laws':
162
- customOptions.config = {}
163
-
164
- if ( $.inArray( 'ccpa', event.data.value ) !== -1 ) {
165
- var htmlElement = $( container ).find( '#hu-cookies-notice-dontsell-btn' );
166
-
167
- if ( htmlElement.length === 0 ) {
168
- $( '#hu-policy-links' ).append( cnHiddenElements.ccpa );
169
-
170
- delete cnHiddenElements.ccpa;
171
- }
172
-
173
- $.extend( customOptions.config, { dontSellLink: true } );
174
- } else {
175
- var htmlElement = $( container ).find( '#hu-cookies-notice-dontsell-btn' );
176
-
177
- // add to hidden elements
178
- if ( htmlElement && ! cnHiddenElements.hasOwnProperty( 'ccpa' ) ) {
179
- cnHiddenElements['ccpa'] = htmlElement;
180
-
181
- // remove el
182
- $( htmlElement ).remove();
183
- }
184
-
185
- $.extend( customOptions.config, { dontSellLink: false } );
186
- }
187
-
188
- if ( $.inArray( 'gdpr', event.data.value ) !== -1 ) {
189
- var htmlElement = $( container ).find( '#hu-cookies-notice-privacy-btn' );
190
-
191
- if ( htmlElement.length === 0 ) {
192
- $( '#hu-policy-links' ).prepend( cnHiddenElements.gdpr );
193
-
194
- delete cnHiddenElements.gdpr;
195
- }
196
-
197
- $.extend( customOptions.config, { privacyPolicyLink: true } );
198
- } else {
199
- var htmlElement = $( container ).find( '#hu-cookies-notice-privacy-btn' );
200
-
201
- // add to hidden elements
202
- if ( htmlElement && ! cnHiddenElements.hasOwnProperty( 'gdpr' ) ) {
203
- cnHiddenElements['gdpr'] = htmlElement;
204
-
205
- // remove el
206
- $( htmlElement ).remove();
207
- }
208
-
209
- $.extend( customOptions.config, { privacyPolicyLink: false } );
210
- }
211
-
212
- // console.log( customOptions );
213
- break;
214
-
215
- case 'privacy_paper':
216
- var value = event.data.value === true;
217
- var htmlElement = $( container ).find( '#hu-cookies-paper' );
218
-
219
- if ( value )
220
- $( htmlElement ).show();
221
- else
222
- $( htmlElement ).hide();
223
-
224
- $.extend( customOptions.config, { privacyPaper: value } );
225
- break;
226
-
227
- case 'privacy_contact':
228
- var value = event.data.value === true;
229
- var htmlElement = $( container ).find( '#hu-cookies-contact');
230
-
231
- if ( value )
232
- $( htmlElement ).show();
233
- else
234
- $( htmlElement ).hide();
235
-
236
- $.extend( customOptions.config, { privacyContact: value } );
237
- break;
238
-
239
- case 'color_primary':
240
- var iframeContents = $( iframe ).contents()[0];
241
- iframeContents.documentElement.style.setProperty( '--hu-primaryColor', event.data.value );
242
- customOptions = { design: { primaryColor: event.data.value } }
243
- break;
244
-
245
- case 'color_background':
246
- var iframeContents = $( iframe ).contents()[0];
247
- iframeContents.documentElement.style.setProperty( '--hu-bannerColor', event.data.value );
248
- customOptions = { design: { bannerColor: event.data.value } }
249
- break;
250
-
251
- case 'color_border':
252
- var iframeContents = $( iframe ).contents()[0];
253
- iframeContents.documentElement.style.setProperty( '--hu-borderColor', event.data.value );
254
- customOptions = { design: { borderColor: event.data.value } }
255
- break;
256
-
257
- case 'color_text':
258
- var iframeContents = $( iframe ).contents()[0];
259
- iframeContents.documentElement.style.setProperty( '--hu-textColor', event.data.value );
260
- customOptions = { design: { textColor: event.data.value } }
261
- break;
262
-
263
- case 'color_heading':
264
- var iframeContents = $( iframe ).contents()[0];
265
- iframeContents.documentElement.style.setProperty( '--hu-headingColor', event.data.value );
266
- customOptions = { design: { headingColor: event.data.value } }
267
- break;
268
-
269
- case 'color_button_text':
270
- var iframeContents = $( iframe ).contents()[0];
271
- iframeContents.documentElement.style.setProperty( '--hu-btnTextColor', event.data.value );
272
- customOptions = { design: { btnTextColor: event.data.value } }
273
- break;
274
- }
275
-
276
- // set widget options
277
- hu.setOptions( customOptions );
278
- // set widget texts
279
- hu.setTexts( customTexts );
280
-
281
- // console.log( hu.options );
282
- }
283
- // remove spinner
284
- $( iframe ).closest( '.has-loader' ).find( '.cn-spinner' ).remove();
285
- $( iframe ).closest( '.has-loader' ).removeClass( 'cn-loading' );
286
- // unlock options
287
- $( form ).removeClass( 'cn-form-disabled' );
288
- }, 500 );
289
-
290
- }, false );
291
-
292
- // is it iframe?
293
- if ( document !== parent.document && typeof cnFrontWelcome !== 'undefined' && cnFrontWelcome.previewMode ) {
294
- // $( parent.document ).find( '#cn_test' ).val( $( document ).find( '.site-title' ).text() );
295
- var iframe = $( parent.document ).find( '#cn_iframe_id' );
296
-
297
- // inject links into initial document
298
- $( document.body ).find( 'a[href], area[href]' ).each( function() {
299
- cnAddPreviewModeToLink( this, iframe );
300
- } );
301
-
302
- // inject links into initial document
303
- $( document.body ).find( 'form' ).each( function() {
304
- cnAddPreviewModeToForm( this, iframe );
305
- } );
306
-
307
- // inject links for new elements added to the page
308
- if ( typeof MutationObserver !== 'undefined' ) {
309
- var observer = new MutationObserver( function( mutations ) {
310
- _.each( mutations, function( mutation ) {
311
- $( mutation.target ).find( 'a[href], area[href]' ).each( function() {
312
- cnAddPreviewModeToLink( this, iframe );
313
- } );
314
-
315
- $( mutation.target ).find( 'form' ).each( function() {
316
- cnAddPreviewModeToForm( this, iframe );
317
- } );
318
- } );
319
- } );
320
-
321
- observer.observe( document.documentElement, {
322
- childList: true,
323
- subtree: true
324
- } );
325
- } else {
326
- // If mutation observers aren't available, fallback to just-in-time injection.
327
- $( document.documentElement ).on( 'click focus mouseover', 'a[href], area[href]', function() {
328
- cnAddPreviewModeToLink( this, iframe );
329
- } );
330
- }
331
-
332
- // remove spinner
333
- $( iframe ).closest( '.has-loader' ).find( '.cn-spinner' ).remove();
334
- $( iframe ).closest( '.has-loader' ).removeClass( 'cn-loading' );
335
- }
336
- } );
337
-
338
- /**
339
- * Inject preview mode parameter into specific links on the frontend.
340
- */
341
- function cnAddPreviewModeToLink( element, iframe ) {
342
- var params, $element = $( element );
343
-
344
- // skip elements with no href attribute
345
- if ( ! element.hasAttribute( 'href' ) )
346
- return;
347
-
348
- // skip links in admin bar
349
- if ( $element.closest( '#wpadminbar' ).length )
350
- return;
351
-
352
- // ignore links with href="#", href="#id", or non-HTTP protocols (e.g. javascript: and mailto:)
353
- if ( '#' === $element.attr( 'href' ).substr( 0, 1 ) || ! /^https?:$/.test( element.protocol ) )
354
- return;
355
-
356
- // make sure links in preview use HTTPS if parent frame uses HTTPS.
357
- // if ( api.settings.channel && 'https' === api.preview.scheme.get() && 'http:' === element.protocol && -1 !== api.settings.url.allowedHosts.indexOf( element.host ) )
358
- // element.protocol = 'https:';
359
-
360
- // ignore links with special class
361
- if ( $element.hasClass( 'wp-playlist-caption' ) )
362
- return;
363
-
364
- // check special links
365
- if ( ! cnIsLinkPreviewable( element ) )
366
- return;
367
-
368
- $( element ).on( 'click', function() {
369
- $( iframe ).closest( '.has-loader' ).addClass( 'cn-loading' );
370
- } );
371
-
372
- // parse query string
373
- params = cnParseQueryString( element.search.substring( 1 ) );
374
-
375
- // set preview mode
376
- params.cn_preview_mode = 1;
377
-
378
- element.search = $.param( params );
379
- }
380
-
381
- /**
382
- * Inject preview mode parameter into specific forms on the frontend.
383
- */
384
- function cnAddPreviewModeToForm( element, iframe ) {
385
- var input = document.createElement( 'input' );
386
-
387
- input.setAttribute( 'type', 'hidden' );
388
- input.setAttribute( 'name', 'cn_preview_mode' );
389
- input.setAttribute( 'value', 1 );
390
-
391
- element.appendChild( input );
392
- }
393
-
394
- /**
395
- * Parse query string.
396
- */
397
- function cnParseQueryString( string ) {
398
- var params = {};
399
-
400
- _.each( string.split( '&' ), function( pair ) {
401
- var parts, key, value;
402
-
403
- parts = pair.split( '=', 2 );
404
-
405
- if ( ! parts[0] )
406
- return;
407
-
408
- key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) );
409
- key = key.replace( / /g, '_' );
410
-
411
- if ( _.isUndefined( parts[1] ) )
412
- value = null;
413
- else
414
- value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) );
415
-
416
- params[ key ] = value;
417
- } );
418
-
419
- return params;
420
- }
421
-
422
- /**
423
- * Whether the supplied link is previewable.
424
- */
425
- function cnIsLinkPreviewable( element ) {
426
- var matchesAllowedUrl, parsedAllowedUrl, elementHost;
427
-
428
- if ( 'javascript:' === element.protocol )
429
- return true;
430
-
431
- // only web URLs can be previewed
432
- if ( element.protocol !== 'https:' && element.protocol !== 'http:' )
433
- return false;
434
-
435
- elementHost = element.host.replace( /:(80|443)$/, '' );
436
- parsedAllowedUrl = document.createElement( 'a' );
437
- matchesAllowedUrl = ! _.isUndefined( _.find( cnFrontWelcome.allowedURLs, function( allowedUrl ) {
438
- parsedAllowedUrl.href = allowedUrl;
439
-
440
- return parsedAllowedUrl.protocol === element.protocol && parsedAllowedUrl.host.replace( /:(80|443)$/, '' ) === elementHost && 0 === element.pathname.indexOf( parsedAllowedUrl.pathname.replace( /\/$/, '' ) );
441
- } ) );
442
-
443
- if ( ! matchesAllowedUrl )
444
- return false;
445
-
446
- // skip wp login and signup pages
447
- if ( /\/wp-(login|signup)\.php$/.test( element.pathname ) )
448
- return false;
449
-
450
- // allow links to admin ajax as faux frontend URLs
451
- if ( /\/wp-admin\/admin-ajax\.php$/.test( element.pathname ) )
452
- return false;
453
-
454
- // disallow links to admin, includes, and content
455
- if ( /\/wp-(admin|includes|content)(\/|$)/.test( element.pathname ) )
456
- return false;
457
-
458
- return true;
459
- };
460
-
461
  } )( jQuery );
1
+ ( function( $ ) {
2
+
3
+ // ready event
4
+ $( function() {
5
+ var cnHiddenElements = {};
6
+
7
+ // listen for the load
8
+ document.addEventListener( 'load.hu', function( e ) {
9
+ // set widget text strings
10
+ hu.setTexts( cnFrontWelcome.textStrings );
11
+ } );
12
+
13
+ // listen for the reload
14
+ document.addEventListener( 'reload.hu', function( e ) {
15
+ var container = $( '#hu' );
16
+ var customOptions = { config: {
17
+ dontSellLink: true,
18
+ privacyPolicyLink: true,
19
+ privacyPaper: true,
20
+ privacyContact: true
21
+ } };
22
+
23
+ // set widget options
24
+ hu.setOptions( customOptions );
25
+ } );
26
+
27
+ // listen for the display
28
+ document.addEventListener( 'display.hu', function( e ) {
29
+ var val = [];
30
+ var container = $( '#hu' );
31
+ var customOptions = { config: {
32
+ // make it empty
33
+ } };
34
+
35
+ $( parent.document ).find( 'input[name="cn_laws"]:checked' ).each( function() {
36
+ val.push( $( this ).val() );
37
+ } );
38
+
39
+ // hide paper and contact
40
+ if ( $( parent.document ).find( 'input[name="cn_privacy_paper"]' ).prop( 'checked' ) === true )
41
+ $( container ).find( '#hu-cookies-paper' ).show();
42
+ else
43
+ $( container ).find( '#hu-cookies-paper' ).hide();
44
+
45
+ if ( $( parent.document ).find( 'input[name="cn_privacy_contact"]' ).prop( 'checked' ) === true )
46
+ $( container ).find( '#hu-cookies-contact' ).show();
47
+ else
48
+ $( container ).find( '#hu-cookies-contact' ).hide();
49
+
50
+ if ( $.inArray( 'ccpa', val ) !== -1 ) {
51
+ var htmlElement = $( $( container ).find( '#hu-cookies-notice-dontsell-btn' ) );
52
+
53
+ if ( htmlElement.length === 0 ) {
54
+ $( '#hu-policy-links' ).append( cnHiddenElements.ccpa );
55
+
56
+ delete cnHiddenElements.ccpa;
57
+ }
58
+
59
+ $.extend( customOptions.config, { dontSellLink: true } );
60
+ } else {
61
+ var htmlElement = $( $( container ).find( '#hu-cookies-notice-dontsell-btn' ) );
62
+
63
+ // add to hidden elements
64
+ if ( htmlElement ) {
65
+ cnHiddenElements['ccpa'] = htmlElement;
66
+
67
+ // remove el
68
+ $( htmlElement ).remove();
69
+ }
70
+
71
+ $.extend( customOptions.config, { dontSellLink: false } );
72
+ }
73
+
74
+ if ( $.inArray( 'gdpr', val ) !== -1 ) {
75
+ var htmlElement = $( $( container ).find( '#hu-cookies-notice-privacy-btn' ) );
76
+
77
+ if ( htmlElement.length === 0 ) {
78
+ $( '#hu-policy-links' ).prepend( cnHiddenElements.gdpr );
79
+
80
+ delete cnHiddenElements.gdpr;
81
+ }
82
+
83
+ $.extend( customOptions.config, { privacyPolicyLink: true } );
84
+ } else {
85
+ var htmlElement = $( $( container ).find( '#hu-cookies-notice-privacy-btn' ) );
86
+
87
+ // add to hidden elements
88
+ if ( htmlElement ) {
89
+ cnHiddenElements['gdpr'] = htmlElement;
90
+
91
+ // remove el
92
+ $( htmlElement ).remove();
93
+ }
94
+
95
+ $.extend( customOptions.config, { privacyPolicyLink: false } );
96
+ }
97
+
98
+ // set widget options
99
+ hu.setOptions( customOptions );
100
+ } );
101
+
102
+ // listen for the parent
103
+ window.addEventListener( 'message', function( event ) {
104
+ var iframe = $( parent.document ).find( '#cn_iframe_id' );
105
+ var form = $( parent.document ).find( '#cn-form-configure' );
106
+
107
+ // add spinner
108
+ $( iframe ).closest( '.has-loader' ).addClass( 'cn-loading' ).append( '<span class="cn-spinner"></span>' );
109
+
110
+ // lock options
111
+ $( form ).addClass( 'cn-form-disabled' );
112
+
113
+ // emit loader
114
+ window.setTimeout( function() {
115
+ if ( typeof event.data == 'object' ) {
116
+ var container = $( '#hu' );
117
+ var option = event.data.call;
118
+ var customOptions = {};
119
+ var customTexts = {};
120
+
121
+ switch ( option ) {
122
+ case 'position':
123
+ $( container ).removeClass( 'hu-position-bottom hu-position-top hu-position-left hu-position-right hu-position-center' );
124
+ $( container ).addClass( 'hu-position-' + event.data.value );
125
+
126
+ customOptions = { design: { position: event.data.value } }
127
+ break;
128
+
129
+ case 'naming':
130
+ var level1 = $( '.hu-cookies-notice-consent-choices-1' );
131
+ var level2 = $( '.hu-cookies-notice-consent-choices-2' );
132
+ var level3 = $( '.hu-cookies-notice-consent-choices-3' );
133
+ var text1 = cnFrontWelcome.levelNames[event.data.value][1];
134
+ var text2 = cnFrontWelcome.levelNames[event.data.value][2];
135
+ var text3 = cnFrontWelcome.levelNames[event.data.value][3];
136
+
137
+ // apply text to dom elements
138
+ $( level1 ).find( '.hu-toggle-label' ).text( text1 );
139
+ $( level2 ).find( '.hu-toggle-label' ).text( text2 );
140
+ $( level3 ).find( '.hu-toggle-label' ).text( text3 );
141
+
142
+ // apply text to text strings
143
+ customTexts = {
144
+ levelNameText_1: text1,
145
+ levelNameText_2: text2,
146
+ levelNameText_3: text3
147
+ }
148
+ break;
149
+
150
+ case 'laws':
151
+ customOptions.config = {}
152
+
153
+ if ( $.inArray( 'ccpa', event.data.value ) !== -1 ) {
154
+ var htmlElement = $( container ).find( '#hu-cookies-notice-dontsell-btn' );
155
+
156
+ if ( htmlElement.length === 0 ) {
157
+ $( '#hu-policy-links' ).append( cnHiddenElements.ccpa );
158
+
159
+ delete cnHiddenElements.ccpa;
160
+ }
161
+
162
+ $.extend( customOptions.config, { dontSellLink: true } );
163
+ } else {
164
+ var htmlElement = $( container ).find( '#hu-cookies-notice-dontsell-btn' );
165
+
166
+ // add to hidden elements
167
+ if ( htmlElement && ! cnHiddenElements.hasOwnProperty( 'ccpa' ) ) {
168
+ cnHiddenElements['ccpa'] = htmlElement;
169
+
170
+ // remove el
171
+ $( htmlElement ).remove();
172
+ }
173
+
174
+ $.extend( customOptions.config, { dontSellLink: false } );
175
+ }
176
+
177
+ if ( $.inArray( 'gdpr', event.data.value ) !== -1 ) {
178
+ var htmlElement = $( container ).find( '#hu-cookies-notice-privacy-btn' );
179
+
180
+ if ( htmlElement.length === 0 ) {
181
+ $( '#hu-policy-links' ).prepend( cnHiddenElements.gdpr );
182
+
183
+ delete cnHiddenElements.gdpr;
184
+ }
185
+
186
+ $.extend( customOptions.config, { privacyPolicyLink: true } );
187
+ } else {
188
+ var htmlElement = $( container ).find( '#hu-cookies-notice-privacy-btn' );
189
+
190
+ // add to hidden elements
191
+ if ( htmlElement && ! cnHiddenElements.hasOwnProperty( 'gdpr' ) ) {
192
+ cnHiddenElements['gdpr'] = htmlElement;
193
+
194
+ // remove el
195
+ $( htmlElement ).remove();
196
+ }
197
+
198
+ $.extend( customOptions.config, { privacyPolicyLink: false } );
199
+ }
200
+
201
+ break;
202
+
203
+ case 'privacy_paper':
204
+ var value = event.data.value === true;
205
+ var htmlElement = $( container ).find( '#hu-cookies-paper' );
206
+
207
+ if ( value )
208
+ $( htmlElement ).show();
209
+ else
210
+ $( htmlElement ).hide();
211
+
212
+ $.extend( customOptions.config, { privacyPaper: value } );
213
+ break;
214
+
215
+ case 'privacy_contact':
216
+ var value = event.data.value === true;
217
+ var htmlElement = $( container ).find( '#hu-cookies-contact');
218
+
219
+ if ( value )
220
+ $( htmlElement ).show();
221
+ else
222
+ $( htmlElement ).hide();
223
+
224
+ $.extend( customOptions.config, { privacyContact: value } );
225
+ break;
226
+
227
+ case 'color_primary':
228
+ var iframeContents = $( iframe ).contents()[0];
229
+
230
+ iframeContents.documentElement.style.setProperty( '--hu-primaryColor', event.data.value );
231
+ customOptions = { design: { primaryColor: event.data.value } }
232
+ break;
233
+
234
+ case 'color_background':
235
+ var iframeContents = $( iframe ).contents()[0];
236
+
237
+ iframeContents.documentElement.style.setProperty( '--hu-bannerColor', event.data.value );
238
+ customOptions = { design: { bannerColor: event.data.value } }
239
+ break;
240
+
241
+ case 'color_border':
242
+ var iframeContents = $( iframe ).contents()[0];
243
+
244
+ iframeContents.documentElement.style.setProperty( '--hu-borderColor', event.data.value );
245
+ customOptions = { design: { borderColor: event.data.value } }
246
+ break;
247
+
248
+ case 'color_text':
249
+ var iframeContents = $( iframe ).contents()[0];
250
+
251
+ iframeContents.documentElement.style.setProperty( '--hu-textColor', event.data.value );
252
+ customOptions = { design: { textColor: event.data.value } }
253
+ break;
254
+
255
+ case 'color_heading':
256
+ var iframeContents = $( iframe ).contents()[0];
257
+
258
+ iframeContents.documentElement.style.setProperty( '--hu-headingColor', event.data.value );
259
+ customOptions = { design: { headingColor: event.data.value } }
260
+ break;
261
+
262
+ case 'color_button_text':
263
+ var iframeContents = $( iframe ).contents()[0];
264
+
265
+ iframeContents.documentElement.style.setProperty( '--hu-btnTextColor', event.data.value );
266
+ customOptions = { design: { btnTextColor: event.data.value } }
267
+ break;
268
+ }
269
+
270
+ // set widget options
271
+ hu.setOptions( customOptions );
272
+
273
+ // set widget texts
274
+ hu.setTexts( customTexts );
275
+ }
276
+
277
+ // remove spinner
278
+ $( iframe ).closest( '.has-loader' ).find( '.cn-spinner' ).remove();
279
+ $( iframe ).closest( '.has-loader' ).removeClass( 'cn-loading' );
280
+
281
+ // unlock options
282
+ $( form ).removeClass( 'cn-form-disabled' );
283
+ }, 500 );
284
+ }, false );
285
+
286
+ // is it iframe?
287
+ if ( document !== parent.document && typeof cnFrontWelcome !== 'undefined' && cnFrontWelcome.previewMode ) {
288
+ var iframe = $( parent.document ).find( '#cn_iframe_id' );
289
+
290
+ // inject links into initial document
291
+ $( document.body ).find( 'a[href], area[href]' ).each( function() {
292
+ cnAddPreviewModeToLink( this, iframe );
293
+ } );
294
+
295
+ // inject links into initial document
296
+ $( document.body ).find( 'form' ).each( function() {
297
+ cnAddPreviewModeToForm( this, iframe );
298
+ } );
299
+
300
+ // inject links for new elements added to the page
301
+ if ( typeof MutationObserver !== 'undefined' ) {
302
+ var observer = new MutationObserver( function( mutations ) {
303
+ _.each( mutations, function( mutation ) {
304
+ $( mutation.target ).find( 'a[href], area[href]' ).each( function() {
305
+ cnAddPreviewModeToLink( this, iframe );
306
+ } );
307
+
308
+ $( mutation.target ).find( 'form' ).each( function() {
309
+ cnAddPreviewModeToForm( this, iframe );
310
+ } );
311
+ } );
312
+ } );
313
+
314
+ observer.observe( document.documentElement, {
315
+ childList: true,
316
+ subtree: true
317
+ } );
318
+ } else {
319
+ // If mutation observers aren't available, fallback to just-in-time injection.
320
+ $( document.documentElement ).on( 'click focus mouseover', 'a[href], area[href]', function() {
321
+ cnAddPreviewModeToLink( this, iframe );
322
+ } );
323
+ }
324
+
325
+ // remove spinner
326
+ $( iframe ).closest( '.has-loader' ).find( '.cn-spinner' ).remove();
327
+ $( iframe ).closest( '.has-loader' ).removeClass( 'cn-loading' );
328
+ }
329
+ } );
330
+
331
+ /**
332
+ * Inject preview mode parameter into specific links on the frontend.
333
+ */
334
+ function cnAddPreviewModeToLink( element, iframe ) {
335
+ var params, $element = $( element );
336
+
337
+ // skip elements with no href attribute
338
+ if ( ! element.hasAttribute( 'href' ) )
339
+ return;
340
+
341
+ // skip links in admin bar
342
+ if ( $element.closest( '#wpadminbar' ).length )
343
+ return;
344
+
345
+ // ignore links with href="#", href="#id", or non-HTTP protocols (e.g. javascript: and mailto:)
346
+ if ( '#' === $element.attr( 'href' ).substr( 0, 1 ) || ! /^https?:$/.test( element.protocol ) )
347
+ return;
348
+
349
+ // make sure links in preview use HTTPS if parent frame uses HTTPS.
350
+ // if ( api.settings.channel && 'https' === api.preview.scheme.get() && 'http:' === element.protocol && -1 !== api.settings.url.allowedHosts.indexOf( element.host ) )
351
+ // element.protocol = 'https:';
352
+
353
+ // ignore links with special class
354
+ if ( $element.hasClass( 'wp-playlist-caption' ) )
355
+ return;
356
+
357
+ // check special links
358
+ if ( ! cnIsLinkPreviewable( element ) )
359
+ return;
360
+
361
+ $( element ).on( 'click', function() {
362
+ $( iframe ).closest( '.has-loader' ).addClass( 'cn-loading' );
363
+ } );
364
+
365
+ // parse query string
366
+ params = cnParseQueryString( element.search.substring( 1 ) );
367
+
368
+ // set preview mode
369
+ params.cn_preview_mode = 1;
370
+
371
+ element.search = $.param( params );
372
+ }
373
+
374
+ /**
375
+ * Inject preview mode parameter into specific forms on the frontend.
376
+ */
377
+ function cnAddPreviewModeToForm( element, iframe ) {
378
+ var input = document.createElement( 'input' );
379
+
380
+ input.setAttribute( 'type', 'hidden' );
381
+ input.setAttribute( 'name', 'cn_preview_mode' );
382
+ input.setAttribute( 'value', 1 );
383
+
384
+ element.appendChild( input );
385
+ }
386
+
387
+ /**
388
+ * Parse query string.
389
+ */
390
+ function cnParseQueryString( string ) {
391
+ var params = {};
392
+
393
+ _.each( string.split( '&' ), function( pair ) {
394
+ var parts, key, value;
395
+
396
+ parts = pair.split( '=', 2 );
397
+
398
+ if ( ! parts[0] )
399
+ return;
400
+
401
+ key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) );
402
+ key = key.replace( / /g, '_' );
403
+
404
+ if ( _.isUndefined( parts[1] ) )
405
+ value = null;
406
+ else
407
+ value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) );
408
+
409
+ params[ key ] = value;
410
+ } );
411
+
412
+ return params;
413
+ }
414
+
415
+ /**
416
+ * Whether the supplied link is previewable.
417
+ */
418
+ function cnIsLinkPreviewable( element ) {
419
+ var matchesAllowedUrl, parsedAllowedUrl, elementHost;
420
+
421
+ if ( 'javascript:' === element.protocol )
422
+ return true;
423
+
424
+ // only web urls can be previewed
425
+ if ( element.protocol !== 'https:' && element.protocol !== 'http:' )
426
+ return false;
427
+
428
+ elementHost = element.host.replace( /:(80|443)$/, '' );
429
+ parsedAllowedUrl = document.createElement( 'a' );
430
+ matchesAllowedUrl = ! _.isUndefined( _.find( cnFrontWelcome.allowedURLs, function( allowedUrl ) {
431
+ parsedAllowedUrl.href = allowedUrl;
432
+
433
+ return parsedAllowedUrl.protocol === element.protocol && parsedAllowedUrl.host.replace( /:(80|443)$/, '' ) === elementHost && 0 === element.pathname.indexOf( parsedAllowedUrl.pathname.replace( /\/$/, '' ) );
434
+ } ) );
435
+
436
+ if ( ! matchesAllowedUrl )
437
+ return false;
438
+
439
+ // skip wp login and signup pages
440
+ if ( /\/wp-(login|signup)\.php$/.test( element.pathname ) )
441
+ return false;
442
+
443
+ // allow links to admin ajax as faux frontend URLs
444
+ if ( /\/wp-admin\/admin-ajax\.php$/.test( element.pathname ) )
445
+ return false;
446
+
447
+ // disallow links to admin, includes, and content
448
+ if ( /\/wp-(admin|includes|content)(\/|$)/.test( element.pathname ) )
449
+ return false;
450
+
451
+ return true;
452
+ };
453
+
 
 
 
 
 
 
 
454
  } )( jQuery );
js/front.js CHANGED
@@ -1,5 +1,5 @@
1
  // CustomEvent polyfil for IE support
2
- ( function () {
3
 
4
  if ( typeof window.CustomEvent === "function" )
5
  return false;
@@ -20,7 +20,7 @@
20
  } )();
21
 
22
  // ClassList polyfil for IE/Safari support
23
- ( function () {
24
  var regExp = function ( name ) {
25
  return new RegExp( '(^| )' + name + '( |$)' );
26
  };
@@ -36,14 +36,14 @@
36
  }
37
 
38
  ClassList.prototype = {
39
- add: function () {
40
  forEach( arguments, function ( name ) {
41
  if ( !this.contains( name ) ) {
42
  this.element.className += this.element.className.length > 0 ? ' ' + name : name;
43
  }
44
  }, this );
45
  },
46
- remove: function () {
47
  forEach( arguments, function ( name ) {
48
  this.element.className =
49
  this.element.className.replace( regExp( name ), '' );
@@ -65,7 +65,7 @@
65
  // IE8/9, Safari
66
  if ( !( 'classList' in Element.prototype ) ) {
67
  Object.defineProperty( Element.prototype, 'classList', {
68
- get: function () {
69
  return new ClassList( this );
70
  }
71
  } );
@@ -78,7 +78,7 @@
78
  // cookieNotice
79
  ( function ( window, document, undefined ) {
80
 
81
- var cookieNotice = new function () {
82
  // cookie status
83
  this.cookiesAccepted = null;
84
 
@@ -88,14 +88,15 @@
88
  // set cookie value
89
  this.setStatus = function ( cookieValue ) {
90
  var _this = this;
 
 
 
 
91
 
92
  // remove listening to scroll event
93
  if ( cnArgs.onScroll === '1' )
94
  window.removeEventListener( 'scroll', this.handleScroll );
95
 
96
- var date = new Date(),
97
- laterDate = new Date();
98
-
99
  // set cookie type and expiry time in seconds
100
  if ( cookieValue === 'accept' ) {
101
  cookieValue = 'true';
@@ -105,8 +106,20 @@
105
  laterDate.setTime( parseInt( date.getTime() ) + parseInt( cnArgs.cookieTimeRejected ) * 1000 );
106
  }
107
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  // set cookie
109
- document.cookie = cnArgs.cookieName + '=' + cookieValue + ';expires=' + laterDate.toUTCString() + ';' + ( !!cnArgs.cookieDomain ? 'domain=' + cnArgs.cookieDomain + ';' : '' ) + ( !!cnArgs.cookiePath ? 'path=' + cnArgs.cookiePath + ';' : '' ) + ( cnArgs.secure === '1' ? 'secure;' : '' );
110
 
111
  // update global status
112
  this.cookiesAccepted = cookieValue === 'true';
@@ -163,6 +176,18 @@
163
  }
164
  };
165
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  // get cookie value
167
  this.getStatus = function ( bool ) {
168
  var value = "; " + document.cookie,
@@ -180,7 +205,7 @@
180
  };
181
 
182
  // display cookie notice
183
- this.showCookieNotice = function () {
184
  var _this = this;
185
 
186
  // trigger custom event
@@ -211,7 +236,7 @@
211
  };
212
 
213
  // hide cookie notice
214
- this.hideCookieNotice = function () {
215
  var _this = this;
216
 
217
  // trigger custom event
@@ -243,7 +268,7 @@
243
  };
244
 
245
  // display revoke notice
246
- this.showRevokeNotice = function () {
247
  var _this = this;
248
 
249
  // trigger custom event
@@ -274,7 +299,7 @@
274
  };
275
 
276
  // hide revoke notice
277
- this.hideRevokeNotice = function () {
278
  var _this = this;
279
 
280
  // trigger custom event
@@ -321,7 +346,7 @@
321
  };
322
 
323
  // handle mouse scrolling
324
- this.handleScroll = function () {
325
  var scrollTop = window.pageYOffset || ( document.documentElement || document.body.parentNode || document.body ).scrollTop
326
 
327
  // accept cookie
@@ -356,27 +381,31 @@
356
 
357
  return null;
358
  };
359
-
360
- // check if displaye in an iframe
361
- this.inIframe = function () {
362
- try {
363
- return window.self !== window.top;
364
- } catch (e) {
365
- return true;
366
- }
367
- }
368
 
369
  // initialize
370
- this.init = function () {
371
  var _this = this;
372
-
373
- // bail if in iframe
374
- if ( this.inIframe() === true )
375
- return;
376
 
377
  this.cookiesAccepted = this.getStatus( true );
378
  this.noticeContainer = document.getElementById( 'cookie-notice' );
379
 
 
 
 
 
380
  var cookieButtons = document.getElementsByClassName( 'cn-set-cookie' ),
381
  revokeButtons = document.getElementsByClassName( 'cn-revoke-cookie' ),
382
  closeIcon = document.getElementById( 'cn-close-notice' );
@@ -424,7 +453,7 @@
424
  _this.setStatus( this.dataset.cookieSet );
425
  } );
426
  }
427
-
428
  // handle close icon
429
  if ( closeIcon !== null ) {
430
  closeIcon.addEventListener( 'click', function ( e ) {
@@ -455,16 +484,15 @@
455
  _this.showCookieNotice();
456
  } );
457
  // show cookie notice
458
- } else if ( _this.noticeContainer.classList.contains( 'cookie-notice-hidden' ) && _this.noticeContainer.classList.contains( 'cookie-revoke-hidden' ) ) {
459
  _this.showCookieNotice();
460
- }
461
  } );
462
  }
463
  };
464
  }
465
 
466
  // initialize plugin
467
- window.addEventListener( 'load', function () {
468
  cookieNotice.init();
469
  }, false );
470
 
1
  // CustomEvent polyfil for IE support
2
+ ( function() {
3
 
4
  if ( typeof window.CustomEvent === "function" )
5
  return false;
20
  } )();
21
 
22
  // ClassList polyfil for IE/Safari support
23
+ ( function() {
24
  var regExp = function ( name ) {
25
  return new RegExp( '(^| )' + name + '( |$)' );
26
  };
36
  }
37
 
38
  ClassList.prototype = {
39
+ add: function() {
40
  forEach( arguments, function ( name ) {
41
  if ( !this.contains( name ) ) {
42
  this.element.className += this.element.className.length > 0 ? ' ' + name : name;
43
  }
44
  }, this );
45
  },
46
+ remove: function() {
47
  forEach( arguments, function ( name ) {
48
  this.element.className =
49
  this.element.className.replace( regExp( name ), '' );
65
  // IE8/9, Safari
66
  if ( !( 'classList' in Element.prototype ) ) {
67
  Object.defineProperty( Element.prototype, 'classList', {
68
+ get: function() {
69
  return new ClassList( this );
70
  }
71
  } );
78
  // cookieNotice
79
  ( function ( window, document, undefined ) {
80
 
81
+ var cookieNotice = new function() {
82
  // cookie status
83
  this.cookiesAccepted = null;
84
 
88
  // set cookie value
89
  this.setStatus = function ( cookieValue ) {
90
  var _this = this;
91
+ var cookieDomain = '';
92
+ var cookiePath = '';
93
+ var date = new Date();
94
+ var laterDate = new Date();
95
 
96
  // remove listening to scroll event
97
  if ( cnArgs.onScroll === '1' )
98
  window.removeEventListener( 'scroll', this.handleScroll );
99
 
 
 
 
100
  // set cookie type and expiry time in seconds
101
  if ( cookieValue === 'accept' ) {
102
  cookieValue = 'true';
106
  laterDate.setTime( parseInt( date.getTime() ) + parseInt( cnArgs.cookieTimeRejected ) * 1000 );
107
  }
108
 
109
+ if ( cnArgs.globalCookie === '1' )
110
+ cookieDomain = this.getDomain( document.location.hostname );
111
+
112
+ // get domain path in localhost
113
+ if ( document.location.hostname === 'localhost' )
114
+ cookiePath = document.location.pathname.split( '/' )[1];
115
+
116
+ var secureValue = '';
117
+
118
+ if ( document.location.protocol === 'https:' )
119
+ secureValue = ';secure';
120
+
121
  // set cookie
122
+ document.cookie = cnArgs.cookieName + '=' + cookieValue + ';expires=' + laterDate.toUTCString() + ';path=/' + cookiePath + ';domain=' + cookieDomain + secureValue;
123
 
124
  // update global status
125
  this.cookiesAccepted = cookieValue === 'true';
176
  }
177
  };
178
 
179
+ // get domain
180
+ this.getDomain = function( url ) {
181
+ var regex = new RegExp( /https?:\/\// );
182
+
183
+ if ( ! regex.test( url ) )
184
+ url = 'http://' + url;
185
+
186
+ var parts = new URL( url ).hostname.split( '.' );
187
+
188
+ return parts.slice( 0 ).slice( -( parts.length === 4 ? 3 : 2 ) ).join( '.' );
189
+ }
190
+
191
  // get cookie value
192
  this.getStatus = function ( bool ) {
193
  var value = "; " + document.cookie,
205
  };
206
 
207
  // display cookie notice
208
+ this.showCookieNotice = function() {
209
  var _this = this;
210
 
211
  // trigger custom event
236
  };
237
 
238
  // hide cookie notice
239
+ this.hideCookieNotice = function() {
240
  var _this = this;
241
 
242
  // trigger custom event
268
  };
269
 
270
  // display revoke notice
271
+ this.showRevokeNotice = function() {
272
  var _this = this;
273
 
274
  // trigger custom event
299
  };
300
 
301
  // hide revoke notice
302
+ this.hideRevokeNotice = function() {
303
  var _this = this;
304
 
305
  // trigger custom event
346
  };
347
 
348
  // handle mouse scrolling
349
+ this.handleScroll = function() {
350
  var scrollTop = window.pageYOffset || ( document.documentElement || document.body.parentNode || document.body ).scrollTop
351
 
352
  // accept cookie
381
 
382
  return null;
383
  };
384
+
385
+ // check if displaye in an iframe
386
+ this.inIframe = function() {
387
+ try {
388
+ return window.self !== window.top;
389
+ } catch (e) {
390
+ return true;
391
+ }
392
+ }
393
 
394
  // initialize
395
+ this.init = function() {
396
  var _this = this;
397
+
398
+ // bail if in iframe
399
+ if ( this.inIframe() === true )
400
+ return;
401
 
402
  this.cookiesAccepted = this.getStatus( true );
403
  this.noticeContainer = document.getElementById( 'cookie-notice' );
404
 
405
+ // no container?
406
+ if ( ! this.noticeContainer )
407
+ return;
408
+
409
  var cookieButtons = document.getElementsByClassName( 'cn-set-cookie' ),
410
  revokeButtons = document.getElementsByClassName( 'cn-revoke-cookie' ),
411
  closeIcon = document.getElementById( 'cn-close-notice' );
453
  _this.setStatus( this.dataset.cookieSet );
454
  } );
455
  }
456
+
457
  // handle close icon
458
  if ( closeIcon !== null ) {
459
  closeIcon.addEventListener( 'click', function ( e ) {
484
  _this.showCookieNotice();
485
  } );
486
  // show cookie notice
487
+ } else if ( _this.noticeContainer.classList.contains( 'cookie-notice-hidden' ) && _this.noticeContainer.classList.contains( 'cookie-revoke-hidden' ) )
488
  _this.showCookieNotice();
 
489
  } );
490
  }
491
  };
492
  }
493
 
494
  // initialize plugin
495
+ window.addEventListener( 'load', function() {
496
  cookieNotice.init();
497
  }, false );
498
 
js/front.min.js CHANGED
@@ -1 +1 @@
1
- !function(){function e(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),n}"function"!=typeof window.CustomEvent&&(e.prototype=window.Event.prototype,window.CustomEvent=e)}(),function(){function t(e){return new RegExp("(^| )"+e+"( |$)")}function e(e,t,n){for(var i=0;i<e.length;i++)t.call(n,e[i])}function n(e){this.element=e}n.prototype={add:function(){e(arguments,function(e){this.contains(e)||(this.element.className+=0<this.element.className.length?" "+e:e)},this)},remove:function(){e(arguments,function(e){this.element.className=this.element.className.replace(t(e),"")},this)},toggle:function(e){return this.contains(e)?(this.remove(e),!1):(this.add(e),!0)},contains:function(e){return t(e).test(this.element.className)},replace:function(e,t){this.remove(e),this.add(t)}},"classList"in Element.prototype||Object.defineProperty(Element.prototype,"classList",{get:function(){return new n(this)}}),window.DOMTokenList&&null==DOMTokenList.prototype.replace&&(DOMTokenList.prototype.replace=n.prototype.replace)}(),function(s,c){var e=new function(){this.cookiesAccepted=null,this.noticeContainer=null,this.setStatus=function(e){var t=this;"1"===cnArgs.onScroll&&s.removeEventListener("scroll",this.handleScroll);var n=new Date,i=new Date;"accept"===e?(e="true",i.setTime(parseInt(n.getTime())+1e3*parseInt(cnArgs.cookieTime))):(e="false",i.setTime(parseInt(n.getTime())+1e3*parseInt(cnArgs.cookieTimeRejected))),c.cookie=cnArgs.cookieName+"="+e+";expires="+i.toUTCString()+";"+(cnArgs.cookieDomain?"domain="+cnArgs.cookieDomain+";":"")+(cnArgs.cookiePath?"path="+cnArgs.cookiePath+";":"")+("1"===cnArgs.secure?"secure;":""),this.cookiesAccepted="true"===e;i=new CustomEvent("setCookieNotice",{detail:{value:e,time:n,expires:i,data:cnArgs}});c.dispatchEvent(i),this.setBodyClass(["cookies-set","true"===e?"cookies-accepted":"cookies-refused"]),this.hideCookieNotice(),"automatic"===cnArgs.revokeCookiesOpt&&(this.noticeContainer.addEventListener("animationend",function e(){t.noticeContainer.removeEventListener("animationend",e),t.showRevokeNotice()}),this.noticeContainer.addEventListener("webkitAnimationEnd",function e(){t.noticeContainer.removeEventListener("webkitAnimationEnd",e),t.showRevokeNotice()})),"1"===cnArgs.redirection&&("true"===e&&null===this.cookiesAccepted||e!==this.cookiesAccepted&&null!==this.cookiesAccepted)&&(i=s.location.protocol+"//",e=s.location.host+"/"+s.location.pathname,"1"===cnArgs.cache?(i=i+e.replace("//","/")+(""===s.location.search?"?":s.location.search+"&")+"cn-reloaded=1"+s.location.hash,s.location.href=i):(i=i+e.replace("//","/")+s.location.search+s.location.hash,s.location.reload(!0)))},this.getStatus=function(e){var t=("; "+c.cookie).split("; cookie_notice_accepted=");if(2!==t.length)return null;t=t.pop().split(";").shift();return e?"true"===t:t},this.showCookieNotice=function(){var t=this,e=new CustomEvent("showCookieNotice",{detail:{data:cnArgs}});c.dispatchEvent(e),this.noticeContainer.classList.remove("cookie-notice-hidden"),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.add("cookie-notice-visible"),this.noticeContainer.addEventListener("animationend",function e(){t.noticeContainer.removeEventListener("animationend",e),t.noticeContainer.classList.remove("cn-animated")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function e(){t.noticeContainer.removeEventListener("webkitAnimationEnd",e),t.noticeContainer.classList.remove("cn-animated")})},this.hideCookieNotice=function(){var t=this,e=new CustomEvent("hideCookieNotice",{detail:{data:cnArgs}});c.dispatchEvent(e),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.remove("cookie-notice-visible"),this.noticeContainer.addEventListener("animationend",function e(){t.noticeContainer.removeEventListener("animationend",e),t.noticeContainer.classList.remove("cn-animated"),t.noticeContainer.classList.add("cookie-notice-hidden")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function e(){t.noticeContainer.removeEventListener("webkitAnimationEnd",e),t.noticeContainer.classList.remove("cn-animated"),t.noticeContainer.classList.add("cookie-notice-hidden")})},this.showRevokeNotice=function(){var t=this,e=new CustomEvent("showRevokeNotice",{detail:{data:cnArgs}});c.dispatchEvent(e),this.noticeContainer.classList.remove("cookie-revoke-hidden"),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.add("cookie-revoke-visible"),this.noticeContainer.addEventListener("animationend",function e(){t.noticeContainer.removeEventListener("animationend",e),t.noticeContainer.classList.remove("cn-animated")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function e(){t.noticeContainer.removeEventListener("webkitAnimationEnd",e),t.noticeContainer.classList.remove("cn-animated")})},this.hideRevokeNotice=function(){var t=this,e=new CustomEvent("hideRevokeNotice",{detail:{data:cnArgs}});c.dispatchEvent(e),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.remove("cookie-revoke-visible"),this.noticeContainer.addEventListener("animationend",function e(){t.noticeContainer.removeEventListener("animationend",e),t.noticeContainer.classList.remove("cn-animated"),t.noticeContainer.classList.add("cookie-revoke-hidden")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function e(){t.noticeContainer.removeEventListener("webkitAnimationEnd",e),t.noticeContainer.classList.remove("cn-animated"),t.noticeContainer.classList.add("cookie-revoke-hidden")})},this.setBodyClass=function(e){c.body.classList.remove("cookies-revoke"),c.body.classList.remove("cookies-accepted"),c.body.classList.remove("cookies-refused"),c.body.classList.remove("cookies-set"),c.body.classList.remove("cookies-not-set");for(var t=0;t<e.length;t++)c.body.classList.add(e[t])},this.handleScroll=function(){(s.pageYOffset||(c.documentElement||c.body.parentNode||c.body).scrollTop)>parseInt(cnArgs.onScrollOffset)&&this.setStatus("accept")},this.getClosest=function(e,t){for(Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(e){for(var t=(this.document||this.ownerDocument).querySelectorAll(e),n=t.length;0<=--n&&t.item(n)!==this;);return-1<n});e&&e!==c;e=e.parentNode)if(e.matches(t))return e;return null},this.inIframe=function(){try{return s.self!==s.top}catch(e){return!0}},this.init=function(){var t=this;if(!0!==this.inIframe()){this.cookiesAccepted=this.getStatus(!0),this.noticeContainer=c.getElementById("cookie-notice");var e=c.getElementsByClassName("cn-set-cookie"),n=c.getElementsByClassName("cn-revoke-cookie"),i=c.getElementById("cn-close-notice");this.noticeContainer.classList.add("cn-effect-"+cnArgs.hideEffect),null===this.cookiesAccepted?("1"===cnArgs.onScroll&&s.addEventListener("scroll",function(e){t.handleScroll()}),"1"===cnArgs.onClick&&s.addEventListener("click",function(e){null===t.getClosest(e.target,"#cookie-notice")&&t.setStatus("accept")},!0),this.setBodyClass(["cookies-not-set"]),this.showCookieNotice()):(this.setBodyClass(["cookies-set",!0===this.cookiesAccepted?"cookies-accepted":"cookies-refused"]),"1"===cnArgs.revokeCookies&&"automatic"===cnArgs.revokeCookiesOpt&&this.showRevokeNotice());for(var o=0;o<e.length;o++)e[o].addEventListener("click",function(e){e.preventDefault(),e.stopPropagation(),t.setStatus(this.dataset.cookieSet)});null!==i&&i.addEventListener("click",function(e){e.preventDefault(),e.stopPropagation(),t.setStatus("reject")});for(o=0;o<n.length;o++)n[o].addEventListener("click",function(e){e.preventDefault(),t.noticeContainer.classList.contains("cookie-revoke-visible")?(t.hideRevokeNotice(),t.noticeContainer.addEventListener("animationend",function e(){t.noticeContainer.removeEventListener("animationend",e),t.showCookieNotice()}),t.noticeContainer.addEventListener("webkitAnimationEnd",function e(){t.noticeContainer.removeEventListener("webkitAnimationEnd",e),t.showCookieNotice()})):t.noticeContainer.classList.contains("cookie-notice-hidden")&&t.noticeContainer.classList.contains("cookie-revoke-hidden")&&t.showCookieNotice()})}}};s.addEventListener("load",function(){e.init()},!1)}(window,document);
1
+ !function(){if("function"==typeof window.CustomEvent)return!1;function a(c,a){a=a||{bubbles:!1,cancelable:!1,detail:void 0};var b=document.createEvent("CustomEvent");return b.initCustomEvent(c,a.bubbles,a.cancelable,a.detail),b}a.prototype=window.Event.prototype,window.CustomEvent=a}(),function(){var b=function(a){return new RegExp("(^| )"+a+"( |$)")},c=function(b,c,d){for(var a=0;a<b.length;a++)c.call(d,b[a])};function a(a){this.element=a}a.prototype={add:function(){c(arguments,function(a){this.contains(a)||(this.element.className+=this.element.className.length>0?" "+a:a)},this)},remove:function(){c(arguments,function(a){this.element.className=this.element.className.replace(b(a),"")},this)},toggle:function(a){return this.contains(a)?(this.remove(a),!1):(this.add(a),!0)},contains:function(a){return b(a).test(this.element.className)},replace:function(a,b){this.remove(a),this.add(b)}},"classList"in Element.prototype||Object.defineProperty(Element.prototype,"classList",{get:function(){return new a(this)}}),window.DOMTokenList&&null==DOMTokenList.prototype.replace&&(DOMTokenList.prototype.replace=a.prototype.replace)}(),function(a,b,c){var d=new function(){this.cookiesAccepted=null,this.noticeContainer=null,this.setStatus=function(c){var l=this,g="",h="",f=new Date,e=new Date;"1"===cnArgs.onScroll&&a.removeEventListener("scroll",this.handleScroll),"accept"===c?(c="true",e.setTime(parseInt(f.getTime())+1e3*parseInt(cnArgs.cookieTime))):(c="false",e.setTime(parseInt(f.getTime())+1e3*parseInt(cnArgs.cookieTimeRejected))),"1"===cnArgs.globalCookie&&(g=this.getDomain(b.location.hostname)),"localhost"===b.location.hostname&&(h=b.location.pathname.split("/")[1]);var i="";"https:"===b.location.protocol&&(i=";secure"),b.cookie=cnArgs.cookieName+"="+c+";expires="+e.toUTCString()+";path=/"+h+";domain="+g+i,this.cookiesAccepted="true"===c;var k=new CustomEvent("setCookieNotice",{detail:{value:c,time:f,expires:e,data:cnArgs}});if(b.dispatchEvent(k),this.setBodyClass(["cookies-set","true"===c?"cookies-accepted":"cookies-refused"]),this.hideCookieNotice(),"automatic"===cnArgs.revokeCookiesOpt&&(this.noticeContainer.addEventListener("animationend",function a(){l.noticeContainer.removeEventListener("animationend",a),l.showRevokeNotice()}),this.noticeContainer.addEventListener("webkitAnimationEnd",function a(){l.noticeContainer.removeEventListener("webkitAnimationEnd",a),l.showRevokeNotice()})),"1"===cnArgs.redirection&&("true"===c&&null===this.cookiesAccepted||c!==this.cookiesAccepted&&null!==this.cookiesAccepted)){var d=a.location.protocol+"//",j=a.location.host+"/"+a.location.pathname;"1"===cnArgs.cache?(d=d+j.replace("//","/")+(""===a.location.search?"?":a.location.search+"&")+"cn-reloaded=1"+a.location.hash,a.location.href=d):(d=d+j.replace("//","/")+a.location.search+a.location.hash,a.location.reload(!0));return}},this.getDomain=function(a){new RegExp(/https?:\/\//).test(a)||(a="http://"+a);var b=new URL(a).hostname.split(".");return b.slice(0).slice(-(4===b.length?3:2)).join(".")},this.getStatus=function(d){var a=("; "+b.cookie).split("; cookie_notice_accepted=");if(2!==a.length)return null;var c=a.pop().split(";").shift();return d?"true"===c:c},this.showCookieNotice=function(){var c=this,a=new CustomEvent("showCookieNotice",{detail:{data:cnArgs}});b.dispatchEvent(a),this.noticeContainer.classList.remove("cookie-notice-hidden"),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.add("cookie-notice-visible"),this.noticeContainer.addEventListener("animationend",function a(){c.noticeContainer.removeEventListener("animationend",a),c.noticeContainer.classList.remove("cn-animated")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function a(){c.noticeContainer.removeEventListener("webkitAnimationEnd",a),c.noticeContainer.classList.remove("cn-animated")})},this.hideCookieNotice=function(){var c=this,a=new CustomEvent("hideCookieNotice",{detail:{data:cnArgs}});b.dispatchEvent(a),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.remove("cookie-notice-visible"),this.noticeContainer.addEventListener("animationend",function a(){c.noticeContainer.removeEventListener("animationend",a),c.noticeContainer.classList.remove("cn-animated"),c.noticeContainer.classList.add("cookie-notice-hidden")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function a(){c.noticeContainer.removeEventListener("webkitAnimationEnd",a),c.noticeContainer.classList.remove("cn-animated"),c.noticeContainer.classList.add("cookie-notice-hidden")})},this.showRevokeNotice=function(){var c=this,a=new CustomEvent("showRevokeNotice",{detail:{data:cnArgs}});b.dispatchEvent(a),this.noticeContainer.classList.remove("cookie-revoke-hidden"),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.add("cookie-revoke-visible"),this.noticeContainer.addEventListener("animationend",function a(){c.noticeContainer.removeEventListener("animationend",a),c.noticeContainer.classList.remove("cn-animated")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function a(){c.noticeContainer.removeEventListener("webkitAnimationEnd",a),c.noticeContainer.classList.remove("cn-animated")})},this.hideRevokeNotice=function(){var c=this,a=new CustomEvent("hideRevokeNotice",{detail:{data:cnArgs}});b.dispatchEvent(a),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.remove("cookie-revoke-visible"),this.noticeContainer.addEventListener("animationend",function a(){c.noticeContainer.removeEventListener("animationend",a),c.noticeContainer.classList.remove("cn-animated"),c.noticeContainer.classList.add("cookie-revoke-hidden")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function a(){c.noticeContainer.removeEventListener("webkitAnimationEnd",a),c.noticeContainer.classList.remove("cn-animated"),c.noticeContainer.classList.add("cookie-revoke-hidden")})},this.setBodyClass=function(c){b.body.classList.remove("cookies-revoke"),b.body.classList.remove("cookies-accepted"),b.body.classList.remove("cookies-refused"),b.body.classList.remove("cookies-set"),b.body.classList.remove("cookies-not-set");for(var a=0;a<c.length;a++)b.body.classList.add(c[a])},this.handleScroll=function(){(a.pageYOffset||(b.documentElement||b.body.parentNode||b.body).scrollTop)>parseInt(cnArgs.onScrollOffset)&&this.setStatus("accept")},this.getClosest=function(a,c){for(Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(c){for(var b=(this.document||this.ownerDocument).querySelectorAll(c),a=b.length;--a>=0&&b.item(a)!==this;);return a> -1});a&&a!==b;a=a.parentNode)if(a.matches(c))return a;return null},this.inIframe=function(){try{return a.self!==a.top}catch(b){return!0}},this.init=function(){var g=this;if(!0!==this.inIframe()&&(this.cookiesAccepted=this.getStatus(!0),this.noticeContainer=b.getElementById("cookie-notice"),this.noticeContainer)){var d=b.getElementsByClassName("cn-set-cookie"),e=b.getElementsByClassName("cn-revoke-cookie"),f=b.getElementById("cn-close-notice");this.noticeContainer.classList.add("cn-effect-"+cnArgs.hideEffect),null===this.cookiesAccepted?("1"===cnArgs.onScroll&&a.addEventListener("scroll",function(a){g.handleScroll()}),"1"===cnArgs.onClick&&a.addEventListener("click",function(a){null===g.getClosest(a.target,"#cookie-notice")&&g.setStatus("accept")},!0),this.setBodyClass(["cookies-not-set"]),this.showCookieNotice()):(this.setBodyClass(["cookies-set",!0===this.cookiesAccepted?"cookies-accepted":"cookies-refused"]),"1"===cnArgs.revokeCookies&&"automatic"===cnArgs.revokeCookiesOpt&&this.showRevokeNotice());for(var c=0;c<d.length;c++)d[c].addEventListener("click",function(a){a.preventDefault(),a.stopPropagation(),g.setStatus(this.dataset.cookieSet)});null!==f&&f.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation(),g.setStatus("reject")});for(var c=0;c<e.length;c++)e[c].addEventListener("click",function(a){a.preventDefault(),g.noticeContainer.classList.contains("cookie-revoke-visible")?(g.hideRevokeNotice(),g.noticeContainer.addEventListener("animationend",function a(){g.noticeContainer.removeEventListener("animationend",a),g.showCookieNotice()}),g.noticeContainer.addEventListener("webkitAnimationEnd",function a(){g.noticeContainer.removeEventListener("webkitAnimationEnd",a),g.showCookieNotice()})):g.noticeContainer.classList.contains("cookie-notice-hidden")&&g.noticeContainer.classList.contains("cookie-revoke-hidden")&&g.showCookieNotice()})}}};a.addEventListener("load",function(){d.init()},!1)}(window,document,void 0)
languages/cookie-notice.pot CHANGED
@@ -1,1294 +1,1330 @@
1
- #, fuzzy
2
- msgid ""
3
- msgstr ""
4
- "Project-Id-Version: Cookie Notice\n"
5
- "POT-Creation-Date: 2022-06-28 22:59+0200\n"
6
- "PO-Revision-Date: 2015-03-24 11:30+0100\n"
7
- "Last-Translator: Bartosz Arendt <info@dfactory.eu>\n"
8
- "Language-Team: dFactory <info@dfactory.eu>\n"
9
- "Language: en\n"
10
- "MIME-Version: 1.0\n"
11
- "Content-Type: text/plain; charset=UTF-8\n"
12
- "Content-Transfer-Encoding: 8bit\n"
13
- "X-Generator: Poedit 3.0.1\n"
14
- "X-Poedit-KeywordsList: gettext;gettext_noop;__;_e;_n\n"
15
- "X-Poedit-Basepath: .\n"
16
- "X-Poedit-SourceCharset: UTF-8\n"
17
- "X-Poedit-SearchPath-0: ..\n"
18
-
19
- #: ../cookie-notice.php:261
20
- msgid "Compliance fines exceeded &euro;1.3 BILLION in 2021. Avoid the risk by making sure your website complies with the latest cookie consent laws."
21
- msgstr ""
22
-
23
- #: ../cookie-notice.php:261
24
- msgid "Run compliance check to learn if your website complies with the latest consent record storage and cookie blocking requirements."
25
- msgstr ""
26
-
27
- #: ../cookie-notice.php:261 ../includes/dashboard.php:485
28
- msgid "Run Compliance Check"
29
- msgstr ""
30
-
31
- #: ../cookie-notice.php:261
32
- msgid "Dismiss Notice"
33
- msgstr ""
34
-
35
- #: ../cookie-notice.php:290
36
- msgid "Cookie Compliance Warning"
37
- msgstr ""
38
-
39
- #: ../cookie-notice.php:290
40
- #, php-format
41
- msgid "Your website has reached the <b>%1$s visits usage limit for the Cookie Compliance Free Plan</b>. Compliance services such as Consent Record Storage, Autoblocking, and Consent Analytics have been deactivated until current usage cycle ends on %2$s."
42
- msgstr ""
43
-
44
- #: ../cookie-notice.php:290
45
- #, php-format
46
- msgid "To reactivate compliance services now, <a href=\"%s\" target=\"_blank\">upgrade your domain to a Pro plan.</a>"
47
- msgstr ""
48
-
49
- #: ../cookie-notice.php:548
50
- msgid "Cookie Notice & Compliance - Deactivation survey"
51
- msgstr ""
52
-
53
- #: ../cookie-notice.php:602
54
- msgid "Settings"
55
- msgstr ""
56
-
57
- #: ../cookie-notice.php:606
58
- msgid "Free Upgrade"
59
- msgstr ""
60
-
61
- #: ../cookie-notice.php:629
62
- msgid "We're sorry to see you go. Could you please tell us what happened?"
63
- msgstr ""
64
-
65
- #: ../cookie-notice.php:633
66
- msgid "I couldn't figure out how to make it work."
67
- msgstr ""
68
-
69
- #: ../cookie-notice.php:634
70
- msgid "I found another plugin to use for the same task."
71
- msgstr ""
72
-
73
- #: ../cookie-notice.php:635
74
- msgid "The Cookie Compliance banner is too big."
75
- msgstr ""
76
-
77
- #: ../cookie-notice.php:636
78
- msgid "The Cookie Compliance consent choices (Silver, Gold, Platinum) are confusing."
79
- msgstr ""
80
-
81
- #: ../cookie-notice.php:637
82
- msgid "The Cookie Compliance default settings are too strict."
83
- msgstr ""
84
-
85
- #: ../cookie-notice.php:638
86
- msgid "The web application user interface is not clear to me."
87
- msgstr ""
88
-
89
- #: ../cookie-notice.php:639
90
- msgid "Support isn't timely."
91
- msgstr ""
92
-
93
- #: ../cookie-notice.php:640
94
- msgid "Other"
95
- msgstr ""
96
-
97
- #: ../cookie-notice.php:654
98
- msgid "Cancel"
99
- msgstr ""
100
-
101
- #: ../cookie-notice.php:655
102
- msgid "Deactivate"
103
- msgstr ""
104
-
105
- #: ../cookie-notice.php:656
106
- msgid "Deactivate & Submit"
107
- msgstr ""
108
-
109
- #: ../includes/dashboard.php:43
110
- msgid "Cookie Compliance"
111
- msgstr ""
112
-
113
- #: ../includes/dashboard.php:149 ../includes/dashboard.php:161
114
- #: ../includes/dashboard.php:173
115
- #, php-format
116
- msgid "Level %s"
117
- msgstr ""
118
-
119
- #: ../includes/dashboard.php:253
120
- msgid "Traffic Overview"
121
- msgstr ""
122
-
123
- #: ../includes/dashboard.php:254
124
- msgid "Displays the general visits information for your domain."
125
- msgstr ""
126
-
127
- #: ../includes/dashboard.php:258
128
- msgid "Consent Activity"
129
- msgstr ""
130
-
131
- #: ../includes/dashboard.php:259
132
- msgid "Displays the chart of the domain consent activity in the last 30 days."
133
- msgstr ""
134
-
135
- #: ../includes/dashboard.php:279
136
- msgid "View consent activity inside WordPress Dashboard"
137
- msgstr ""
138
-
139
- #: ../includes/dashboard.php:280
140
- msgid "Display information about the visits."
141
- msgstr ""
142
-
143
- #: ../includes/dashboard.php:281
144
- msgid "Get Consent logs data for the last 30 days."
145
- msgstr ""
146
-
147
- #: ../includes/dashboard.php:282
148
- msgid "Enable consent purpose categories, automatic cookie blocking and more."
149
- msgstr ""
150
-
151
- #: ../includes/dashboard.php:283
152
- msgid "Upgrade to Cookie Compliance"
153
- msgstr ""
154
-
155
- #: ../includes/dashboard.php:375
156
- msgid "Total Visits"
157
- msgstr ""
158
-
159
- #: ../includes/dashboard.php:377
160
- msgid "Last 30 days"
161
- msgstr ""
162
-
163
- #: ../includes/dashboard.php:380
164
- msgid "Consent Logs"
165
- msgstr ""
166
-
167
- #: ../includes/dashboard.php:382
168
- #, php-format
169
- msgid "Updated %s"
170
- msgstr ""
171
-
172
- #: ../includes/dashboard.php:400
173
- msgid "Traffic Usage"
174
- msgstr ""
175
-
176
- #: ../includes/dashboard.php:403
177
- #, php-format
178
- msgid "Visits usage: %1$s / %2$s"
179
- msgstr ""
180
-
181
- #: ../includes/dashboard.php:404
182
- #, php-format
183
- msgid "Cycle started: %s"
184
- msgstr ""
185
-
186
- #: ../includes/dashboard.php:405
187
- #, php-format
188
- msgid "Days to go: %s"
189
- msgstr ""
190
-
191
- #: ../includes/dashboard.php:454
192
- msgid "Cookie Compliance Status"
193
- msgstr ""
194
-
195
- #: ../includes/dashboard.php:475
196
- msgid "Your site does not have Cookie Compliance"
197
- msgstr ""
198
-
199
- #: ../includes/dashboard.php:478 ../includes/settings.php:186
200
- #: ../includes/welcome.php:401
201
- msgid "Cookie Notice"
202
- msgstr ""
203
-
204
- #: ../includes/dashboard.php:481
205
- msgid "Run Compliance Check to determine your site's compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws."
206
- msgstr ""
207
-
208
- #: ../includes/settings.php:46 ../includes/welcome.php:478
209
- msgid "Top"
210
- msgstr ""
211
-
212
- #: ../includes/settings.php:47 ../includes/welcome.php:477
213
- msgid "Bottom"
214
- msgstr ""
215
-
216
- #: ../includes/settings.php:51 ../includes/settings.php:97
217
- msgid "None"
218
- msgstr ""
219
-
220
- #: ../includes/settings.php:52
221
- msgid "Light"
222
- msgstr ""
223
-
224
- #: ../includes/settings.php:53
225
- msgid "Dark"
226
- msgstr ""
227
-
228
- #: ../includes/settings.php:57
229
- msgid "Automatic"
230
- msgstr ""
231
-
232
- #: ../includes/settings.php:58
233
- msgid "Manual"
234
- msgstr ""
235
-
236
- #: ../includes/settings.php:62
237
- msgid "Page link"
238
- msgstr ""
239
-
240
- #: ../includes/settings.php:63
241
- msgid "Custom link"
242
- msgstr ""
243
-
244
- #: ../includes/settings.php:72
245
- msgid "Banner"
246
- msgstr ""
247
-
248
- #: ../includes/settings.php:73 ../includes/settings.php:302
249
- msgid "Message"
250
- msgstr ""
251
-
252
- #: ../includes/settings.php:77
253
- msgid "Text color"
254
- msgstr ""
255
-
256
- #: ../includes/settings.php:78
257
- msgid "Button color"
258
- msgstr ""
259
-
260
- #: ../includes/settings.php:79
261
- msgid "Bar color"
262
- msgstr ""
263
-
264
- #: ../includes/settings.php:85
265
- msgid "An hour"
266
- msgstr ""
267
-
268
- #: ../includes/settings.php:86
269
- msgid "1 day"
270
- msgstr ""
271
-
272
- #: ../includes/settings.php:87
273
- msgid "1 week"
274
- msgstr ""
275
-
276
- #: ../includes/settings.php:88
277
- msgid "1 month"
278
- msgstr ""
279
-
280
- #: ../includes/settings.php:89
281
- msgid "3 months"
282
- msgstr ""
283
-
284
- #: ../includes/settings.php:90
285
- msgid "6 months"
286
- msgstr ""
287
-
288
- #: ../includes/settings.php:91
289
- msgid "1 year"
290
- msgstr ""
291
-
292
- #: ../includes/settings.php:92
293
- msgid "infinity"
294
- msgstr ""
295
-
296
- #: ../includes/settings.php:98
297
- msgid "Fade"
298
- msgstr ""
299
-
300
- #: ../includes/settings.php:99
301
- msgid "Slide"
302
- msgstr ""
303
-
304
- #: ../includes/settings.php:103
305
- msgid "Header"
306
- msgstr ""
307
-
308
- #: ../includes/settings.php:104
309
- msgid "Footer"
310
- msgstr ""
311
-
312
- #: ../includes/settings.php:109
313
- msgid "Silver"
314
- msgstr ""
315
-
316
- #: ../includes/settings.php:110
317
- msgid "Gold"
318
- msgstr ""
319
-
320
- #: ../includes/settings.php:111
321
- msgid "Platinum"
322
- msgstr ""
323
-
324
- #: ../includes/settings.php:114
325
- msgid "Private"
326
- msgstr ""
327
-
328
- #: ../includes/settings.php:115
329
- msgid "Balanced"
330
- msgstr ""
331
-
332
- #: ../includes/settings.php:116
333
- msgid "Personalized"
334
- msgstr ""
335
-
336
- #: ../includes/settings.php:119
337
- msgid "Reject All"
338
- msgstr ""
339
-
340
- #: ../includes/settings.php:120
341
- msgid "Accept Some"
342
- msgstr ""
343
-
344
- #: ../includes/settings.php:121
345
- msgid "Accept All"
346
- msgstr ""
347
-
348
- #: ../includes/settings.php:126
349
- msgid "Save my preferences"
350
- msgstr ""
351
-
352
- #: ../includes/settings.php:130 ../includes/settings.php:151
353
- #: ../includes/settings.php:304
354
- msgid "Privacy policy"
355
- msgstr ""
356
-
357
- #: ../includes/settings.php:131
358
- msgid "Do Not Sell"
359
- msgstr ""
360
-
361
- #: ../includes/settings.php:132
362
- msgid "Preferences"
363
- msgstr ""
364
-
365
- #: ../includes/settings.php:133
366
- msgid "We believe your data is your property and support your right to privacy and transparency."
367
- msgstr ""
368
-
369
- #: ../includes/settings.php:134
370
- msgid "Select a Data Access Level and Duration to choose how we use and share your data."
371
- msgstr ""
372
-
373
- #: ../includes/settings.php:135
374
- msgid "Highest level of privacy. Data accessed for necessary site operations only. Data shared with 3rd parties to ensure the site is secure and works on your device."
375
- msgstr ""
376
-
377
- #: ../includes/settings.php:136
378
- msgid "Balanced experience. Data accessed for content personalisation and site optimisation. Data shared with 3rd parties may be used to track and store your preferences for this site."
379
- msgstr ""
380
-
381
- #: ../includes/settings.php:137
382
- msgid "Highest level of personalisation. Data accessed to make ads and media more relevant. Data shared with 3rd parties may be use to track you on this site and other sites you visit."
383
- msgstr ""
384
-
385
- #: ../includes/settings.php:141
386
- msgid "month"
387
- msgstr ""
388
-
389
- #: ../includes/settings.php:142
390
- msgid "months"
391
- msgstr ""
392
-
393
- #: ../includes/settings.php:146
394
- msgid "We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it."
395
- msgstr ""
396
-
397
- #: ../includes/settings.php:147
398
- msgid "Ok"
399
- msgstr ""
400
-
401
- #: ../includes/settings.php:148
402
- msgid "No"
403
- msgstr ""
404
-
405
- #: ../includes/settings.php:149
406
- msgid "You can revoke your consent any time using the Revoke consent button."
407
- msgstr ""
408
-
409
- #: ../includes/settings.php:150 ../includes/settings.php:306
410
- msgid "Revoke consent"
411
- msgstr ""
412
-
413
- #: ../includes/settings.php:186
414
- msgid "Cookies"
415
- msgstr ""
416
-
417
- #: ../includes/settings.php:197
418
- msgid "Cookie Notice & Compliance for GDPR/CCPA"
419
- msgstr ""
420
-
421
- #: ../includes/settings.php:207
422
- msgid "Promote the privacy of your website visitors without affecting how you do your business."
423
- msgstr ""
424
-
425
- #: ../includes/settings.php:210 ../includes/welcome.php:196
426
- #: ../includes/welcome.php:237
427
- msgid "The next generation of Cookie Notice"
428
- msgstr ""
429
-
430
- #: ../includes/settings.php:212
431
- msgid "A free web application to help you deliver better consent experiences and comply with GDPR, CCPA and other data privacy laws more effectively."
432
- msgstr ""
433
-
434
- #: ../includes/settings.php:215
435
- msgid "Learn more"
436
- msgstr ""
437
-
438
- #: ../includes/settings.php:226
439
- msgid "F.A.Q."
440
- msgstr ""
441
-
442
- #: ../includes/settings.php:230
443
- msgid "Does the Cookie Notice make my site fully compliant with GDPR?"
444
- msgstr ""
445
-
446
- #: ../includes/settings.php:231
447
- msgid "It is not possible to provide the required technical compliance features using only a WordPress plugin. Features like consent record storage, purpose categories and script blocking that bring your site into full compliance with GDPR are only available through the Cookie Compliance integration."
448
- msgstr ""
449
-
450
- #: ../includes/settings.php:235
451
- msgid "Does the Cookie Compiance integration make my site fully compliant with GDPR?"
452
- msgstr ""
453
-
454
- #: ../includes/settings.php:236
455
- msgid "Yes! The plugin + web application version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions."
456
- msgstr ""
457
-
458
- #: ../includes/settings.php:240
459
- msgid "Is Cookie Compliance free?"
460
- msgstr ""
461
-
462
- #: ../includes/settings.php:241
463
- msgid "Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website monthly traffic."
464
- msgstr ""
465
-
466
- #: ../includes/settings.php:245
467
- msgid "Where can I find pricing options?"
468
- msgstr ""
469
-
470
- #: ../includes/settings.php:246
471
- msgid "You can learn more about the features and pricing by visiting the Cookie Compliance website here:"
472
- msgstr ""
473
-
474
- #: ../includes/settings.php:263
475
- msgid "Reset to defaults"
476
- msgstr ""
477
-
478
- #: ../includes/settings.php:281 ../includes/settings.php:296
479
- msgid "Compliance Settings"
480
- msgstr ""
481
-
482
- #: ../includes/settings.php:282 ../includes/settings.php:297
483
- msgid "Compliance status"
484
- msgstr ""
485
-
486
- #: ../includes/settings.php:283 ../includes/settings.php:298
487
- msgid "App ID"
488
- msgstr ""
489
-
490
- #: ../includes/settings.php:284 ../includes/settings.php:299
491
- msgid "App Key"
492
- msgstr ""
493
-
494
- #: ../includes/settings.php:286
495
- msgid "Miscellaneous Settings"
496
- msgstr ""
497
-
498
- #: ../includes/settings.php:287 ../includes/settings.php:344
499
- #: ../includes/settings.php:359 ../includes/settings.php:374
500
- #: ../includes/welcome.php:402
501
- msgid "Autoblocking"
502
- msgstr ""
503
-
504
- #: ../includes/settings.php:288
505
- msgid "Hide for logged in"
506
- msgstr ""
507
-
508
- #: ../includes/settings.php:289
509
- msgid "Debug mode"
510
- msgstr ""
511
-
512
- #: ../includes/settings.php:290
513
- msgid "Cache"
514
- msgstr ""
515
-
516
- #: ../includes/settings.php:291 ../includes/settings.php:313
517
- msgid "Script placement"
518
- msgstr ""
519
-
520
- #: ../includes/settings.php:292 ../includes/settings.php:314
521
- msgid "Deactivation"
522
- msgstr ""
523
-
524
- #: ../includes/settings.php:301
525
- msgid "Notice Settings"
526
- msgstr ""
527
-
528
- #: ../includes/settings.php:303
529
- msgid "Button text"
530
- msgstr ""
531
-
532
- #: ../includes/settings.php:305
533
- msgid "Refuse consent"
534
- msgstr ""
535
-
536
- #: ../includes/settings.php:307
537
- msgid "Script blocking"
538
- msgstr ""
539
-
540
- #: ../includes/settings.php:308
541
- msgid "Reloading"
542
- msgstr ""
543
-
544
- #: ../includes/settings.php:309
545
- msgid "On scroll"
546
- msgstr ""
547
-
548
- #: ../includes/settings.php:310
549
- msgid "On click"
550
- msgstr ""
551
-
552
- #: ../includes/settings.php:311
553
- msgid "Accepted expiry"
554
- msgstr ""
555
-
556
- #: ../includes/settings.php:312
557
- msgid "Rejected expiry"
558
- msgstr ""
559
-
560
- #: ../includes/settings.php:317
561
- msgid "Notice Design"
562
- msgstr ""
563
-
564
- #: ../includes/settings.php:318
565
- msgid "Position"
566
- msgstr ""
567
-
568
- #: ../includes/settings.php:319
569
- msgid "Animation"
570
- msgstr ""
571
-
572
- #: ../includes/settings.php:320
573
- msgid "Colors"
574
- msgstr ""
575
-
576
- #: ../includes/settings.php:321
577
- msgid "Button class"
578
- msgstr ""
579
-
580
- #: ../includes/settings.php:343 ../includes/settings.php:358
581
- #: ../includes/settings.php:373
582
- msgid "Notice"
583
- msgstr ""
584
-
585
- #: ../includes/settings.php:343 ../includes/settings.php:344
586
- #: ../includes/settings.php:345 ../includes/settings.php:346
587
- #: ../includes/settings.php:358 ../includes/settings.php:373
588
- msgid "Active"
589
- msgstr ""
590
-
591
- #: ../includes/settings.php:345 ../includes/settings.php:360
592
- #: ../includes/settings.php:375 ../includes/welcome.php:403
593
- msgid "Cookie Categories"
594
- msgstr ""
595
-
596
- #: ../includes/settings.php:346 ../includes/settings.php:361
597
- #: ../includes/settings.php:376 ../includes/welcome.php:404
598
- msgid "Proof-of-Consent"
599
- msgstr ""
600
-
601
- #: ../includes/settings.php:349
602
- msgid "Log in & Configure"
603
- msgstr ""
604
-
605
- #: ../includes/settings.php:350
606
- msgid "Log into the Cookie Compliance&trade; web application and configure your Privacy Experience."
607
- msgstr ""
608
-
609
- #: ../includes/settings.php:359 ../includes/settings.php:360
610
- #: ../includes/settings.php:361
611
- msgid "Pending"
612
- msgstr ""
613
-
614
- #: ../includes/settings.php:364
615
- msgid "Log in & configure"
616
- msgstr ""
617
-
618
- #: ../includes/settings.php:365
619
- msgid "Log into the Cookie Compliance&trade; web application and complete the setup process."
620
- msgstr ""
621
-
622
- #: ../includes/settings.php:374 ../includes/settings.php:375
623
- #: ../includes/settings.php:376
624
- msgid "Inactive"
625
- msgstr ""
626
-
627
- #: ../includes/settings.php:379
628
- msgid "Add Compliance features"
629
- msgstr ""
630
-
631
- #: ../includes/settings.php:380
632
- msgid "Sign up to Cookie Compliance&trade; and add GDPR, CCPA and other international data privacy laws compliance features."
633
- msgstr ""
634
-
635
- #: ../includes/settings.php:395
636
- msgid "Enter your Cookie Compliance&trade; application ID."
637
- msgstr ""
638
-
639
- #: ../includes/settings.php:407
640
- msgid "Enter your Cookie Compliance&trade; application secret key."
641
- msgstr ""
642
-
643
- #: ../includes/settings.php:417
644
- msgid "Enable to automatically block 3rd party scripts before user consent."
645
- msgstr ""
646
-
647
- #: ../includes/settings.php:418
648
- msgid "In case you're experiencing issues with your site disable that feature temporarily."
649
- msgstr ""
650
-
651
- #: ../includes/settings.php:429
652
- msgid "Purge Cache"
653
- msgstr ""
654
-
655
- #: ../includes/settings.php:431
656
- msgid "Click the Purge Cache button to refresh the app configuration."
657
- msgstr ""
658
-
659
- #: ../includes/settings.php:441
660
- msgid "Enable to hide the consent banner for logged in users."
661
- msgstr ""
662
-
663
- #: ../includes/settings.php:451
664
- msgid "Enable to run the consent banner in debug mode."
665
- msgstr ""
666
-
667
- #: ../includes/settings.php:462
668
- msgid "Enter the cookie notice message."
669
- msgstr ""
670
-
671
- #: ../includes/settings.php:473
672
- msgid "The text of the option to accept the notice and make it disappear."
673
- msgstr ""
674
-
675
- #: ../includes/settings.php:483
676
- msgid "Enable to give to the user the possibility to refuse third party non functional cookies."
677
- msgstr ""
678
-
679
- #: ../includes/settings.php:487
680
- msgid "The text of the button to refuse the consent."
681
- msgstr ""
682
-
683
- #: ../includes/settings.php:505
684
- msgid "Head"
685
- msgstr ""
686
-
687
- #: ../includes/settings.php:506
688
- msgid "Body"
689
- msgstr ""
690
-
691
- #: ../includes/settings.php:509
692
- msgid "The code to be used in your site header, before the closing head tag."
693
- msgstr ""
694
-
695
- #: ../includes/settings.php:513
696
- msgid "The code to be used in your site footer, before the closing body tag."
697
- msgstr ""
698
-
699
- #: ../includes/settings.php:517
700
- msgid "Enter non functional cookies Javascript code here (for e.g. Google Analitycs) to be used after the notice is accepted."
701
- msgstr ""
702
-
703
- #: ../includes/settings.php:517
704
- msgid "To get the user consent status use the <code>cn_cookies_accepted()</code> function."
705
- msgstr ""
706
-
707
- #: ../includes/settings.php:528
708
- msgid "Enable to give to the user the possibility to revoke their consent <i>(requires \"Refuse consent\" option enabled)</i>."
709
- msgstr ""
710
-
711
- #: ../includes/settings.php:531
712
- msgid "Enter the revoke message."
713
- msgstr ""
714
-
715
- #: ../includes/settings.php:533
716
- msgid "The text of the button to revoke the consent."
717
- msgstr ""
718
-
719
- #: ../includes/settings.php:541
720
- msgid "Select the method for displaying the revoke button - automatic (in the banner) or manual using <code>[cookies_revoke]</code> shortcode."
721
- msgstr ""
722
-
723
- #: ../includes/settings.php:552
724
- msgid "Enable to reload the page after the notice is accepted."
725
- msgstr ""
726
-
727
- #: ../includes/settings.php:575
728
- msgid "Enable privacy policy link."
729
- msgstr ""
730
-
731
- #: ../includes/settings.php:578
732
- msgid "The text of the privacy policy button."
733
- msgstr ""
734
-
735
- #: ../includes/settings.php:590
736
- msgid "Select where to redirect user for more information."
737
- msgstr ""
738
-
739
- #: ../includes/settings.php:593
740
- msgid "-- select page --"
741
- msgstr ""
742
-
743
- #: ../includes/settings.php:604
744
- msgid "Select from one of your site's pages."
745
- msgstr ""
746
-
747
- #: ../includes/settings.php:610
748
- msgid "Synchronize with WordPress Privacy Policy page."
749
- msgstr ""
750
-
751
- #: ../includes/settings.php:617
752
- msgid "Enter the full URL starting with http(s)://"
753
- msgstr ""
754
-
755
- #: ../includes/settings.php:660
756
- msgid "The amount of time that the cookie should be stored for when user accepts the notice."
757
- msgstr ""
758
-
759
- #: ../includes/settings.php:683
760
- msgid "The amount of time that the cookie should be stored for when the user doesn't accept the notice."
761
- msgstr ""
762
-
763
- #: ../includes/settings.php:701
764
- msgid "Select where all the plugin scripts should be placed."
765
- msgstr ""
766
-
767
- #: ../includes/settings.php:721
768
- msgid "Select location for the notice."
769
- msgstr ""
770
-
771
- #: ../includes/settings.php:742
772
- msgid "Select the animation style."
773
- msgstr ""
774
-
775
- #: ../includes/settings.php:753
776
- msgid "Enable to accept the notice when user scrolls."
777
- msgstr ""
778
-
779
- #: ../includes/settings.php:756
780
- msgid "Number of pixels user has to scroll to accept the notice and make it disappear."
781
- msgstr ""
782
-
783
- #: ../includes/settings.php:767
784
- msgid "Enable to accept the notice on any click on the page."
785
- msgstr ""
786
-
787
- #: ../includes/settings.php:777
788
- msgid "Enable if you want all plugin data to be deleted on deactivation."
789
- msgstr ""
790
-
791
- #: ../includes/settings.php:789
792
- msgid "Enter additional button CSS classes separated by spaces."
793
- msgstr ""
794
-
795
- #: ../includes/settings.php:813
796
- msgid "Bar opacity"
797
- msgstr ""
798
-
799
- #: ../includes/settings.php:958
800
- msgid "Settings saved."
801
- msgstr ""
802
-
803
- #: ../includes/settings.php:965
804
- msgid "Settings restored to defaults."
805
- msgstr ""
806
-
807
- #: ../includes/settings.php:990
808
- msgid "Are you sure you want to reset these settings to defaults?"
809
- msgstr ""
810
-
811
- #: ../includes/welcome-api.php:37 ../includes/welcome-api.php:40
812
- #: ../includes/welcome-api.php:43 ../includes/welcome-api.php:46
813
- #: ../includes/welcome.php:165 ../includes/welcome.php:175
814
- #: ../includes/welcome.php:178
815
- msgid "You do not have permission to access this page."
816
- msgstr ""
817
-
818
- #: ../includes/welcome-api.php:97 ../includes/welcome-api.php:301
819
- #: ../includes/welcome-api.php:340 ../includes/welcome-api.php:466
820
- #: ../includes/welcome-api.php:538 ../includes/welcome-api.php:1016
821
- #: ../includes/welcome.php:70
822
- msgid "Unexpected error occurred. Please try again later."
823
- msgstr ""
824
-
825
- #: ../includes/welcome-api.php:122
826
- msgid "Empty plan or payment method data."
827
- msgstr ""
828
-
829
- #: ../includes/welcome-api.php:157
830
- msgid "Unable to create customer data."
831
- msgstr ""
832
-
833
- #: ../includes/welcome-api.php:206
834
- msgid "Unable to create payment mehotd."
835
- msgstr ""
836
-
837
- #: ../includes/welcome-api.php:212
838
- msgid "No payment method token."
839
- msgstr ""
840
-
841
- #: ../includes/welcome-api.php:243
842
- msgid "Please accept the Terms of Service to proceed."
843
- msgstr ""
844
-
845
- #: ../includes/welcome-api.php:248 ../includes/welcome-api.php:437
846
- msgid "Email is not allowed to be empty."
847
- msgstr ""
848
-
849
- #: ../includes/welcome-api.php:253 ../includes/welcome-api.php:442
850
- msgid "Password is not allowed to be empty."
851
- msgstr ""
852
-
853
- #: ../includes/welcome-api.php:258
854
- msgid "Passwords do not match."
855
- msgstr ""
856
-
857
- #: ../includes/welcome.php:71
858
- msgid "Passed"
859
- msgstr ""
860
-
861
- #: ../includes/welcome.php:72
862
- msgid "Failed"
863
- msgstr ""
864
-
865
- #: ../includes/welcome.php:73 ../includes/welcome.php:318
866
- #: ../includes/welcome.php:571 ../includes/welcome.php:673
867
- msgid "monthly"
868
- msgstr ""
869
-
870
- #: ../includes/welcome.php:74
871
- msgid "yearly"
872
- msgstr ""
873
-
874
- #: ../includes/welcome.php:78
875
- msgid "<em>Compliance Failed!</em>Your website does not achieve minimum viable compliance. <b><a href=\"#\" class=\"cn-sign-up\">Sign up to Cookie Compliance</a></b> to bring your site into compliance with the latest data privacy rules and regulations."
876
- msgstr ""
877
-
878
- #: ../includes/welcome.php:79
879
- msgid "<em>Compliance Passed!</em>Congratulations. Your website meets minimum viable compliance."
880
- msgstr ""
881
-
882
- #: ../includes/welcome.php:80 ../includes/welcome.php:675
883
- msgid "available"
884
- msgstr ""
885
-
886
- #: ../includes/welcome.php:81
887
- msgid "Please fill all the required fields."
888
- msgstr ""
889
-
890
- #: ../includes/welcome.php:198
891
- msgid "Cookie Compliance is a free web application that enables websites to take a proactive approach to data protection and consent laws."
892
- msgstr ""
893
-
894
- #: ../includes/welcome.php:204
895
- msgid "It is the first solution to offer <b>intentional consent</b>, a new consent framework that incorporates the latest guidelines from over 100+ countries, and emerging standards from leading international organizations like the IEEE."
896
- msgstr ""
897
-
898
- #: ../includes/welcome.php:205
899
- msgid "Cookie Notice includes <b>seamless integration</b> with Cookie Compliance to help your site comply with the latest updates to existing consent laws and provide a beautiful, multi-level experience to engage visitors in data privacy decisions."
900
- msgstr ""
901
-
902
- #: ../includes/welcome.php:209
903
- msgid "Sign up to Cookie Compliance"
904
- msgstr ""
905
-
906
- #: ../includes/welcome.php:210
907
- msgid "Skip for now"
908
- msgstr ""
909
-
910
- #: ../includes/welcome.php:239
911
- msgid "Take a proactive approach to data protection and consent laws by signing up for Cookie Compliance account. Then select a limited Basic Plan for free or get one of the Professional Plans for unlimited visits, consent storage, languages and customizations."
912
- msgstr ""
913
-
914
- #: ../includes/welcome.php:283
915
- msgid "Compliance Plans"
916
- msgstr ""
917
-
918
- #: ../includes/welcome.php:286
919
- msgid "Monthly"
920
- msgstr ""
921
-
922
- #: ../includes/welcome.php:289
923
- msgid "Yearly"
924
- msgstr ""
925
-
926
- #: ../includes/welcome.php:289
927
- msgid "Save 12%"
928
- msgstr ""
929
-
930
- #: ../includes/welcome.php:297 ../includes/welcome.php:570
931
- #: ../includes/welcome.php:672
932
- msgid "Basic"
933
- msgstr ""
934
-
935
- #: ../includes/welcome.php:298
936
- msgid "Free"
937
- msgstr ""
938
-
939
- #: ../includes/welcome.php:301 ../includes/welcome.php:330
940
- msgid "GDPR, CCPA, ePrivacy, PECR compliance"
941
- msgstr ""
942
-
943
- #: ../includes/welcome.php:302 ../includes/welcome.php:331
944
- msgid "Consent Analytics Dashboard"
945
- msgstr ""
946
-
947
- #: ../includes/welcome.php:303
948
- msgid "<b>1,000</b> visits / month"
949
- msgstr ""
950
-
951
- #: ../includes/welcome.php:304
952
- msgid "<b>30 days</b> consent storage"
953
- msgstr ""
954
-
955
- #: ../includes/welcome.php:305
956
- msgid "<b>1 additional</b> language"
957
- msgstr ""
958
-
959
- #: ../includes/welcome.php:306
960
- msgid "<b>Basic</b> Support"
961
- msgstr ""
962
-
963
- #: ../includes/welcome.php:309
964
- msgid "Start Basic"
965
- msgstr ""
966
-
967
- #: ../includes/welcome.php:317
968
- msgid "Professional"
969
- msgstr ""
970
-
971
- #: ../includes/welcome.php:319
972
- msgid "Recommended"
973
- msgstr ""
974
-
975
- #: ../includes/welcome.php:321
976
- msgid "Pricing options"
977
- msgstr ""
978
-
979
- #: ../includes/welcome.php:322 ../includes/welcome.php:323
980
- #: ../includes/welcome.php:324 ../includes/welcome.php:325
981
- #, php-format
982
- msgid "%s domain license"
983
- msgstr ""
984
-
985
- #: ../includes/welcome.php:332
986
- msgid "<b>Unlimited</b> visits"
987
- msgstr ""
988
-
989
- #: ../includes/welcome.php:333
990
- msgid "<b>Lifetime</b> consent storage"
991
- msgstr ""
992
-
993
- #: ../includes/welcome.php:334
994
- msgid "<b>Unlimited</b> languages"
995
- msgstr ""
996
-
997
- #: ../includes/welcome.php:335
998
- msgid "<b>Premium</b> Support"
999
- msgstr ""
1000
-
1001
- #: ../includes/welcome.php:338
1002
- msgid "Start Premium"
1003
- msgstr ""
1004
-
1005
- #: ../includes/welcome.php:344
1006
- msgid "I don’t want to create an account now"
1007
- msgstr ""
1008
-
1009
- #: ../includes/welcome.php:360
1010
- msgid "Congratulations"
1011
- msgstr ""
1012
-
1013
- #: ../includes/welcome.php:361
1014
- msgid "You are now promoting privacy with Hu-manity.co"
1015
- msgstr ""
1016
-
1017
- #: ../includes/welcome.php:363
1018
- msgid "Log in to your Cookie Compliance&trade; account and continue configuring your Privacy Experience."
1019
- msgstr ""
1020
-
1021
- #: ../includes/welcome.php:366
1022
- msgid "Go to Application"
1023
- msgstr ""
1024
-
1025
- #: ../includes/welcome.php:391
1026
- msgid "Compliance check"
1027
- msgstr ""
1028
-
1029
- #: ../includes/welcome.php:392
1030
- msgid "This is a Compliance Check to determine your site’s compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws."
1031
- msgstr ""
1032
-
1033
- #: ../includes/welcome.php:394
1034
- msgid "Site URL"
1035
- msgstr ""
1036
-
1037
- #: ../includes/welcome.php:395
1038
- msgid "Site Name"
1039
- msgstr ""
1040
-
1041
- #: ../includes/welcome.php:398
1042
- msgid "Checking..."
1043
- msgstr ""
1044
-
1045
- #: ../includes/welcome.php:401
1046
- msgid "Notifies visitors that site uses cookies."
1047
- msgstr ""
1048
-
1049
- #: ../includes/welcome.php:402
1050
- msgid "Non-essential cookies blocked until consent is registered."
1051
- msgstr ""
1052
-
1053
- #: ../includes/welcome.php:403
1054
- msgid "Separate consent requested per purpose of use."
1055
- msgstr ""
1056
-
1057
- #: ../includes/welcome.php:404
1058
- msgid "Proof-of-consent stored in secure audit format."
1059
- msgstr ""
1060
-
1061
- #: ../includes/welcome.php:420
1062
- msgid "Live Setup"
1063
- msgstr ""
1064
-
1065
- #: ../includes/welcome.php:421
1066
- msgid "Configure your Cookie Notice & Compliance design and compliance features through the options below. Click Apply Setup to save the configuration and go to selecting your preferred cookie solution."
1067
- msgstr ""
1068
-
1069
- #: ../includes/welcome.php:425
1070
- msgid "Banner Compliance"
1071
- msgstr ""
1072
-
1073
- #: ../includes/welcome.php:446
1074
- msgid "Select the laws that apply to your business"
1075
- msgstr ""
1076
-
1077
- #: ../includes/welcome.php:448
1078
- msgid "GDPR"
1079
- msgstr ""
1080
-
1081
- #: ../includes/welcome.php:449
1082
- msgid "CCPA"
1083
- msgstr ""
1084
-
1085
- #: ../includes/welcome.php:453
1086
- msgid "Select a naming style for the consent choices"
1087
- msgstr ""
1088
-
1089
- #: ../includes/welcome.php:455
1090
- msgid "Silver, Gold, Platinum (Default)​"
1091
- msgstr ""
1092
-
1093
- #: ../includes/welcome.php:456
1094
- msgid "Private, Balanced, Personalized"
1095
- msgstr ""
1096
-
1097
- #: ../includes/welcome.php:457
1098
- msgid "Reject All, Accept Some, Accept All​"
1099
- msgstr ""
1100
-
1101
- #: ../includes/welcome.php:461
1102
- msgid "Select additional information to include in the banner:"
1103
- msgstr ""
1104
-
1105
- #: ../includes/welcome.php:463
1106
- msgid "Display <b>Privacy Paper</b> to provide helpful data privacy and consent information to visitors."
1107
- msgstr ""
1108
-
1109
- #: ../includes/welcome.php:464
1110
- msgid "Display <b>Privacy Contact</b> to provide Data Controller contact information and links to external data privacy resources."
1111
- msgstr ""
1112
-
1113
- #: ../includes/welcome.php:467 ../includes/welcome.php:495
1114
- msgid "available for Cookie Compliance&trade; Pro plans only"
1115
- msgstr ""
1116
-
1117
- #: ../includes/welcome.php:471
1118
- msgid "Banner Design"
1119
- msgstr ""
1120
-
1121
- #: ../includes/welcome.php:475
1122
- msgid "Select your preferred display position"
1123
- msgstr ""
1124
-
1125
- #: ../includes/welcome.php:479
1126
- msgid "Left"
1127
- msgstr ""
1128
-
1129
- #: ../includes/welcome.php:480
1130
- msgid "Right"
1131
- msgstr ""
1132
-
1133
- #: ../includes/welcome.php:481
1134
- msgid "Center"
1135
- msgstr ""
1136
-
1137
- #: ../includes/welcome.php:485
1138
- msgid "Adjust the banner color scheme"
1139
- msgstr ""
1140
-
1141
- #: ../includes/welcome.php:487
1142
- msgid "Color of the buttons and interactive elements."
1143
- msgstr ""
1144
-
1145
- #: ../includes/welcome.php:488
1146
- msgid "Color of the banner background."
1147
- msgstr ""
1148
-
1149
- #: ../includes/welcome.php:489
1150
- msgid "Color of the body text."
1151
- msgstr ""
1152
-
1153
- #: ../includes/welcome.php:490
1154
- msgid "Color of the borders and inactive elements."
1155
- msgstr ""
1156
-
1157
- #: ../includes/welcome.php:491
1158
- msgid "Color of the heading text."
1159
- msgstr ""
1160
-
1161
- #: ../includes/welcome.php:492
1162
- msgid "Color of the button text."
1163
- msgstr ""
1164
-
1165
- #: ../includes/welcome.php:500
1166
- msgid "Apply Setup"
1167
- msgstr ""
1168
-
1169
- #: ../includes/welcome.php:518
1170
- msgid "Compliance account"
1171
- msgstr ""
1172
-
1173
- #: ../includes/welcome.php:520
1174
- msgid "Create a Cookie Compliance&trade; account and select your preferred plan."
1175
- msgstr ""
1176
-
1177
- #: ../includes/welcome.php:524
1178
- msgid "Create Account"
1179
- msgstr ""
1180
-
1181
- #: ../includes/welcome.php:529 ../includes/welcome.php:639
1182
- msgid "Email address"
1183
- msgstr ""
1184
-
1185
- #: ../includes/welcome.php:532 ../includes/welcome.php:642
1186
- msgid "Password"
1187
- msgstr ""
1188
-
1189
- #: ../includes/welcome.php:535
1190
- msgid "Confirm Password"
1191
- msgstr ""
1192
-
1193
- #: ../includes/welcome.php:539
1194
- #, php-format
1195
- msgid "I have read and agree to the <a href=\"%s\" target=\"_blank\">Terms of Service"
1196
- msgstr ""
1197
-
1198
- #: ../includes/welcome.php:543
1199
- msgid "Sign Up"
1200
- msgstr ""
1201
-
1202
- #: ../includes/welcome.php:557
1203
- msgid "Already have an account?"
1204
- msgstr ""
1205
-
1206
- #: ../includes/welcome.php:557 ../includes/welcome.php:645
1207
- msgid "Sign in"
1208
- msgstr ""
1209
-
1210
- #: ../includes/welcome.php:564 ../includes/welcome.php:666
1211
- msgid "Select Plan"
1212
- msgstr ""
1213
-
1214
- #: ../includes/welcome.php:571 ../includes/welcome.php:673
1215
- msgid "<b>Professional</b>"
1216
- msgstr ""
1217
-
1218
- #: ../includes/welcome.php:575 ../includes/welcome.php:681
1219
- #: ../includes/welcome.php:722
1220
- msgid "Confirm"
1221
- msgstr ""
1222
-
1223
- #: ../includes/welcome.php:580 ../includes/welcome.php:687
1224
- msgid "Payment Method"
1225
- msgstr ""
1226
-
1227
- #: ../includes/welcome.php:582 ../includes/welcome.php:689
1228
- msgid "Credit Card"
1229
- msgstr ""
1230
-
1231
- #: ../includes/welcome.php:583 ../includes/welcome.php:690
1232
- msgid "PayPal"
1233
- msgstr ""
1234
-
1235
- #: ../includes/welcome.php:589 ../includes/welcome.php:696
1236
- msgid "Card Number"
1237
- msgstr ""
1238
-
1239
- #: ../includes/welcome.php:593 ../includes/welcome.php:700
1240
- msgid "Expiration Date"
1241
- msgstr ""
1242
-
1243
- #: ../includes/welcome.php:597 ../includes/welcome.php:704
1244
- msgid "CVC/CVV"
1245
- msgstr ""
1246
-
1247
- #: ../includes/welcome.php:601 ../includes/welcome.php:708
1248
- msgid "Submit"
1249
- msgstr ""
1250
-
1251
- #: ../includes/welcome.php:628
1252
- msgid "Compliance Sign in"
1253
- msgstr ""
1254
-
1255
- #: ../includes/welcome.php:630
1256
- msgid "Sign in to your existing Cookie Compliance&trade; account and select your preferred plan."
1257
- msgstr ""
1258
-
1259
- #: ../includes/welcome.php:634
1260
- msgid "Account Login"
1261
- msgstr ""
1262
-
1263
- #: ../includes/welcome.php:659
1264
- msgid "Don't have an account yet?"
1265
- msgstr ""
1266
-
1267
- #: ../includes/welcome.php:659
1268
- msgid "Sign up"
1269
- msgstr ""
1270
-
1271
- #: ../includes/welcome.php:675
1272
- msgid "Use License"
1273
- msgstr ""
1274
-
1275
- #: ../includes/welcome.php:718
1276
- msgid "Select subscription"
1277
- msgstr ""
1278
-
1279
- #: ../includes/welcome.php:719
1280
- msgid "Licenses"
1281
- msgstr ""
1282
-
1283
- #: ../includes/welcome.php:742
1284
- msgid "Success!"
1285
- msgstr ""
1286
-
1287
- #: ../includes/welcome.php:743
1288
- msgid "You have successfully upgraded your website to Cookie Compliance&trade;"
1289
- msgstr ""
1290
-
1291
- #: ../includes/welcome.php:743
1292
- #, php-format
1293
- msgid "Go to Cookie Compliance&trade; application now. Or access it anytime from your <a href=\"%s\">Cookie Notice settings page</a>."
1294
- msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #, fuzzy
2
+ msgid ""
3
+ msgstr ""
4
+ "Project-Id-Version: Cookie Notice\n"
5
+ "POT-Creation-Date: 2022-08-24 11:16+0200\n"
6
+ "PO-Revision-Date: 2015-03-24 11:30+0100\n"
7
+ "Last-Translator: Bartosz Arendt <info@dfactory.eu>\n"
8
+ "Language-Team: dFactory <info@dfactory.eu>\n"
9
+ "Language: en\n"
10
+ "MIME-Version: 1.0\n"
11
+ "Content-Type: text/plain; charset=UTF-8\n"
12
+ "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Generator: Poedit 3.1.1\n"
14
+ "X-Poedit-KeywordsList: gettext;gettext_noop;__;_e;_n\n"
15
+ "X-Poedit-Basepath: .\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-SearchPath-0: ..\n"
18
+
19
+ #: ../cookie-notice.php:573
20
+ msgid "German Court Fines Website Owner for Using Google-Hosted Fonts"
21
+ msgstr ""
22
+
23
+ #: ../cookie-notice.php:573
24
+ msgid "The German Court ruled that use of Google Fonts without prior consent is a violation of Europe’s GDPR (General Data Protection Regulation) because Google Fonts exposes the visitor’s IP address. Court’s ruling threatens a fine of €250,000 for each case of infringement if the site owner does not comply. If your website uses Google Fonts, click \"Run Compliance Check\" to make sure your website complies with the latest consent capture and cookie blocking requirements."
25
+ msgstr ""
26
+
27
+ #: ../cookie-notice.php:573 ../includes/dashboard.php:518
28
+ msgid "Run Compliance Check"
29
+ msgstr ""
30
+
31
+ #: ../cookie-notice.php:573
32
+ msgid "Dismiss Notice"
33
+ msgstr ""
34
+
35
+ #: ../cookie-notice.php:608
36
+ msgid "Cookie Compliance Warning"
37
+ msgstr ""
38
+
39
+ #: ../cookie-notice.php:608
40
+ #, php-format
41
+ msgid "Your website has reached the <b>%1$s visits usage limit for the Cookie Compliance Free Plan</b>. Compliance services such as Consent Record Storage, Autoblocking, and Consent Analytics have been deactivated until current usage cycle ends on %2$s."
42
+ msgstr ""
43
+
44
+ #: ../cookie-notice.php:608
45
+ #, php-format
46
+ msgid "To reactivate compliance services now, <a href=\"%s\" target=\"_blank\">upgrade your domain to a Pro plan.</a>"
47
+ msgstr ""
48
+
49
+ #: ../cookie-notice.php:930
50
+ msgid "Cookie Notice & Compliance - Deactivation survey"
51
+ msgstr ""
52
+
53
+ #: ../cookie-notice.php:996
54
+ msgid "Settings"
55
+ msgstr ""
56
+
57
+ #: ../cookie-notice.php:1009
58
+ msgid "Free Upgrade"
59
+ msgstr ""
60
+
61
+ #: ../cookie-notice.php:1034
62
+ msgid "We're sorry to see you go. Could you please tell us what happened?"
63
+ msgstr ""
64
+
65
+ #: ../cookie-notice.php:1038
66
+ msgid "I couldn't figure out how to make it work."
67
+ msgstr ""
68
+
69
+ #: ../cookie-notice.php:1039
70
+ msgid "I found another plugin to use for the same task."
71
+ msgstr ""
72
+
73
+ #: ../cookie-notice.php:1040
74
+ msgid "The Cookie Compliance banner is too big."
75
+ msgstr ""
76
+
77
+ #: ../cookie-notice.php:1041
78
+ msgid "The Cookie Compliance consent choices (Silver, Gold, Platinum) are confusing."
79
+ msgstr ""
80
+
81
+ #: ../cookie-notice.php:1042
82
+ msgid "The Cookie Compliance default settings are too strict."
83
+ msgstr ""
84
+
85
+ #: ../cookie-notice.php:1043
86
+ msgid "The web application user interface is not clear to me."
87
+ msgstr ""
88
+
89
+ #: ../cookie-notice.php:1044
90
+ msgid "Support isn't timely."
91
+ msgstr ""
92
+
93
+ #: ../cookie-notice.php:1045
94
+ msgid "Other"
95
+ msgstr ""
96
+
97
+ #: ../cookie-notice.php:1059
98
+ msgid "Cancel"
99
+ msgstr ""
100
+
101
+ #: ../cookie-notice.php:1060
102
+ msgid "Deactivate"
103
+ msgstr ""
104
+
105
+ #: ../cookie-notice.php:1061
106
+ msgid "Deactivate & Submit"
107
+ msgstr ""
108
+
109
+ #: ../includes/dashboard.php:72
110
+ msgid "Cookie Compliance"
111
+ msgstr ""
112
+
113
+ #: ../includes/dashboard.php:175 ../includes/dashboard.php:187
114
+ #: ../includes/dashboard.php:199
115
+ #, php-format
116
+ msgid "Level %s"
117
+ msgstr ""
118
+
119
+ #: ../includes/dashboard.php:288
120
+ msgid "Traffic Overview"
121
+ msgstr ""
122
+
123
+ #: ../includes/dashboard.php:289
124
+ msgid "Displays the general visits information for your domain."
125
+ msgstr ""
126
+
127
+ #: ../includes/dashboard.php:293
128
+ msgid "Consent Activity"
129
+ msgstr ""
130
+
131
+ #: ../includes/dashboard.php:294
132
+ msgid "Displays the chart of the domain consent activity in the last 30 days."
133
+ msgstr ""
134
+
135
+ #: ../includes/dashboard.php:314
136
+ msgid "View consent activity inside WordPress Dashboard"
137
+ msgstr ""
138
+
139
+ #: ../includes/dashboard.php:315
140
+ msgid "Display information about the visits."
141
+ msgstr ""
142
+
143
+ #: ../includes/dashboard.php:316
144
+ msgid "Get Consent logs data for the last 30 days."
145
+ msgstr ""
146
+
147
+ #: ../includes/dashboard.php:317
148
+ msgid "Enable consent purpose categories, automatic cookie blocking and more."
149
+ msgstr ""
150
+
151
+ #: ../includes/dashboard.php:318
152
+ msgid "Upgrade to Cookie Compliance"
153
+ msgstr ""
154
+
155
+ #: ../includes/dashboard.php:419
156
+ msgid "Total Visits"
157
+ msgstr ""
158
+
159
+ #: ../includes/dashboard.php:421
160
+ msgid "Last 30 days"
161
+ msgstr ""
162
+
163
+ #: ../includes/dashboard.php:424
164
+ msgid "Consent Logs"
165
+ msgstr ""
166
+
167
+ #: ../includes/dashboard.php:426
168
+ #, php-format
169
+ msgid "Updated %s"
170
+ msgstr ""
171
+
172
+ #: ../includes/dashboard.php:443
173
+ msgid "Traffic Usage"
174
+ msgstr ""
175
+
176
+ #: ../includes/dashboard.php:446
177
+ #, php-format
178
+ msgid "Visits usage: %1$s / %2$s"
179
+ msgstr ""
180
+
181
+ #: ../includes/dashboard.php:447
182
+ #, php-format
183
+ msgid "Cycle started: %s"
184
+ msgstr ""
185
+
186
+ #: ../includes/dashboard.php:448
187
+ #, php-format
188
+ msgid "Days to go: %s"
189
+ msgstr ""
190
+
191
+ #: ../includes/dashboard.php:491
192
+ msgid "Cookie Compliance Status"
193
+ msgstr ""
194
+
195
+ #: ../includes/dashboard.php:511
196
+ msgid "Your site does not have Cookie Compliance"
197
+ msgstr ""
198
+
199
+ #: ../includes/dashboard.php:514 ../includes/settings.php:200
200
+ #: ../includes/welcome.php:415
201
+ msgid "Cookie Notice"
202
+ msgstr ""
203
+
204
+ #: ../includes/dashboard.php:517
205
+ msgid "Run Compliance Check to determine your site's compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws."
206
+ msgstr ""
207
+
208
+ #: ../includes/settings.php:52 ../includes/welcome.php:492
209
+ msgid "Top"
210
+ msgstr ""
211
+
212
+ #: ../includes/settings.php:53 ../includes/welcome.php:491
213
+ msgid "Bottom"
214
+ msgstr ""
215
+
216
+ #: ../includes/settings.php:57 ../includes/settings.php:100
217
+ msgid "None"
218
+ msgstr ""
219
+
220
+ #: ../includes/settings.php:58
221
+ msgid "Light"
222
+ msgstr ""
223
+
224
+ #: ../includes/settings.php:59
225
+ msgid "Dark"
226
+ msgstr ""
227
+
228
+ #: ../includes/settings.php:63
229
+ msgid "Automatic"
230
+ msgstr ""
231
+
232
+ #: ../includes/settings.php:64
233
+ msgid "Manual"
234
+ msgstr ""
235
+
236
+ #: ../includes/settings.php:68
237
+ msgid "Page link"
238
+ msgstr ""
239
+
240
+ #: ../includes/settings.php:69
241
+ msgid "Custom link"
242
+ msgstr ""
243
+
244
+ #: ../includes/settings.php:75
245
+ msgid "Banner"
246
+ msgstr ""
247
+
248
+ #: ../includes/settings.php:76 ../includes/settings.php:381
249
+ msgid "Message"
250
+ msgstr ""
251
+
252
+ #: ../includes/settings.php:80
253
+ msgid "Text color"
254
+ msgstr ""
255
+
256
+ #: ../includes/settings.php:81
257
+ msgid "Button color"
258
+ msgstr ""
259
+
260
+ #: ../includes/settings.php:82
261
+ msgid "Bar color"
262
+ msgstr ""
263
+
264
+ #: ../includes/settings.php:88
265
+ msgid "An hour"
266
+ msgstr ""
267
+
268
+ #: ../includes/settings.php:89
269
+ msgid "1 day"
270
+ msgstr ""
271
+
272
+ #: ../includes/settings.php:90
273
+ msgid "1 week"
274
+ msgstr ""
275
+
276
+ #: ../includes/settings.php:91
277
+ msgid "1 month"
278
+ msgstr ""
279
+
280
+ #: ../includes/settings.php:92
281
+ msgid "3 months"
282
+ msgstr ""
283
+
284
+ #: ../includes/settings.php:93
285
+ msgid "6 months"
286
+ msgstr ""
287
+
288
+ #: ../includes/settings.php:94
289
+ msgid "1 year"
290
+ msgstr ""
291
+
292
+ #: ../includes/settings.php:95
293
+ msgid "infinity"
294
+ msgstr ""
295
+
296
+ #: ../includes/settings.php:101
297
+ msgid "Fade"
298
+ msgstr ""
299
+
300
+ #: ../includes/settings.php:102
301
+ msgid "Slide"
302
+ msgstr ""
303
+
304
+ #: ../includes/settings.php:106
305
+ msgid "Header"
306
+ msgstr ""
307
+
308
+ #: ../includes/settings.php:107
309
+ msgid "Footer"
310
+ msgstr ""
311
+
312
+ #: ../includes/settings.php:112
313
+ msgid "Silver"
314
+ msgstr ""
315
+
316
+ #: ../includes/settings.php:113
317
+ msgid "Gold"
318
+ msgstr ""
319
+
320
+ #: ../includes/settings.php:114
321
+ msgid "Platinum"
322
+ msgstr ""
323
+
324
+ #: ../includes/settings.php:117
325
+ msgid "Private"
326
+ msgstr ""
327
+
328
+ #: ../includes/settings.php:118
329
+ msgid "Balanced"
330
+ msgstr ""
331
+
332
+ #: ../includes/settings.php:119
333
+ msgid "Personalized"
334
+ msgstr ""
335
+
336
+ #: ../includes/settings.php:122
337
+ msgid "Reject All"
338
+ msgstr ""
339
+
340
+ #: ../includes/settings.php:123
341
+ msgid "Accept Some"
342
+ msgstr ""
343
+
344
+ #: ../includes/settings.php:124
345
+ msgid "Accept All"
346
+ msgstr ""
347
+
348
+ #: ../includes/settings.php:129
349
+ msgid "Save my preferences"
350
+ msgstr ""
351
+
352
+ #: ../includes/settings.php:133 ../includes/settings.php:157
353
+ #: ../includes/settings.php:383
354
+ msgid "Privacy policy"
355
+ msgstr ""
356
+
357
+ #: ../includes/settings.php:134
358
+ msgid "Do Not Sell"
359
+ msgstr ""
360
+
361
+ #: ../includes/settings.php:135
362
+ msgid "Preferences"
363
+ msgstr ""
364
+
365
+ #: ../includes/settings.php:136
366
+ msgid "We believe your data is your property and support your right to privacy and transparency."
367
+ msgstr ""
368
+
369
+ #: ../includes/settings.php:137
370
+ msgid "Select a Data Access Level and Duration to choose how we use and share your data."
371
+ msgstr ""
372
+
373
+ #: ../includes/settings.php:138
374
+ msgid "Highest level of privacy. Data accessed for necessary site operations only. Data shared with 3rd parties to ensure the site is secure and works on your device."
375
+ msgstr ""
376
+
377
+ #: ../includes/settings.php:139
378
+ msgid "Balanced experience. Data accessed for content personalisation and site optimisation. Data shared with 3rd parties may be used to track and store your preferences for this site."
379
+ msgstr ""
380
+
381
+ #: ../includes/settings.php:140
382
+ msgid "Highest level of personalisation. Data accessed to make ads and media more relevant. Data shared with 3rd parties may be use to track you on this site and other sites you visit."
383
+ msgstr ""
384
+
385
+ #: ../includes/settings.php:144
386
+ msgid "month"
387
+ msgstr ""
388
+
389
+ #: ../includes/settings.php:145
390
+ msgid "months"
391
+ msgstr ""
392
+
393
+ #: ../includes/settings.php:152
394
+ msgid "We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it."
395
+ msgstr ""
396
+
397
+ #: ../includes/settings.php:153
398
+ msgid "Ok"
399
+ msgstr ""
400
+
401
+ #: ../includes/settings.php:154
402
+ msgid "No"
403
+ msgstr ""
404
+
405
+ #: ../includes/settings.php:155
406
+ msgid "You can revoke your consent any time using the Revoke consent button."
407
+ msgstr ""
408
+
409
+ #: ../includes/settings.php:156 ../includes/settings.php:385
410
+ msgid "Revoke consent"
411
+ msgstr ""
412
+
413
+ #: ../includes/settings.php:200
414
+ msgid "Cookies"
415
+ msgstr ""
416
+
417
+ #: ../includes/settings.php:217
418
+ msgid "Cookie Notice & Compliance for GDPR/CCPA"
419
+ msgstr ""
420
+
421
+ #: ../includes/settings.php:227
422
+ msgid "Promote the privacy of your website visitors without affecting how you do your business."
423
+ msgstr ""
424
+
425
+ #: ../includes/settings.php:230 ../includes/welcome.php:213
426
+ #: ../includes/welcome.php:253
427
+ msgid "The next generation of Cookie Notice"
428
+ msgstr ""
429
+
430
+ #: ../includes/settings.php:232
431
+ msgid "A free web application to help you deliver better consent experiences and comply with GDPR, CCPA and other data privacy laws more effectively."
432
+ msgstr ""
433
+
434
+ #: ../includes/settings.php:235
435
+ msgid "Learn more"
436
+ msgstr ""
437
+
438
+ #: ../includes/settings.php:246
439
+ msgid "F.A.Q."
440
+ msgstr ""
441
+
442
+ #: ../includes/settings.php:250
443
+ msgid "Does the Cookie Notice make my site fully compliant with GDPR?"
444
+ msgstr ""
445
+
446
+ #: ../includes/settings.php:251
447
+ msgid "It is not possible to provide the required technical compliance features using only a WordPress plugin. Features like consent record storage, purpose categories and script blocking that bring your site into full compliance with GDPR are only available through the Cookie Compliance integration."
448
+ msgstr ""
449
+
450
+ #: ../includes/settings.php:255
451
+ msgid "Does the Cookie Compiance integration make my site fully compliant with GDPR?"
452
+ msgstr ""
453
+
454
+ #: ../includes/settings.php:256
455
+ msgid "Yes! The plugin + web application version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions."
456
+ msgstr ""
457
+
458
+ #: ../includes/settings.php:260
459
+ msgid "Is Cookie Compliance free?"
460
+ msgstr ""
461
+
462
+ #: ../includes/settings.php:261
463
+ msgid "Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website monthly traffic."
464
+ msgstr ""
465
+
466
+ #: ../includes/settings.php:265
467
+ msgid "Where can I find pricing options?"
468
+ msgstr ""
469
+
470
+ #: ../includes/settings.php:266
471
+ msgid "You can learn more about the features and pricing by visiting the Cookie Compliance website here:"
472
+ msgstr ""
473
+
474
+ #: ../includes/settings.php:312
475
+ msgid "Reset to defaults"
476
+ msgstr ""
477
+
478
+ #: ../includes/settings.php:339 ../includes/settings.php:344
479
+ msgid "Network Settings"
480
+ msgstr ""
481
+
482
+ #: ../includes/settings.php:340
483
+ msgid "Global Settings Override"
484
+ msgstr ""
485
+
486
+ #: ../includes/settings.php:341
487
+ msgid "Global Cookie"
488
+ msgstr ""
489
+
490
+ #: ../includes/settings.php:358 ../includes/settings.php:374
491
+ msgid "Compliance Settings"
492
+ msgstr ""
493
+
494
+ #: ../includes/settings.php:359 ../includes/settings.php:375
495
+ msgid "Compliance status"
496
+ msgstr ""
497
+
498
+ #: ../includes/settings.php:360 ../includes/settings.php:376
499
+ msgid "App ID"
500
+ msgstr ""
501
+
502
+ #: ../includes/settings.php:361 ../includes/settings.php:377
503
+ msgid "App Key"
504
+ msgstr ""
505
+
506
+ #: ../includes/settings.php:364
507
+ msgid "Miscellaneous Settings"
508
+ msgstr ""
509
+
510
+ #: ../includes/settings.php:365 ../includes/settings.php:465
511
+ #: ../includes/settings.php:479 ../includes/settings.php:498
512
+ #: ../includes/welcome.php:416
513
+ msgid "Autoblocking"
514
+ msgstr ""
515
+
516
+ #: ../includes/settings.php:366
517
+ msgid "Hide for logged in"
518
+ msgstr ""
519
+
520
+ #: ../includes/settings.php:367
521
+ msgid "Debug mode"
522
+ msgstr ""
523
+
524
+ #: ../includes/settings.php:368
525
+ msgid "Cache"
526
+ msgstr ""
527
+
528
+ #: ../includes/settings.php:369 ../includes/settings.php:392
529
+ msgid "Script placement"
530
+ msgstr ""
531
+
532
+ #: ../includes/settings.php:370 ../includes/settings.php:393
533
+ msgid "Deactivation"
534
+ msgstr ""
535
+
536
+ #: ../includes/settings.php:380
537
+ msgid "Notice Settings"
538
+ msgstr ""
539
+
540
+ #: ../includes/settings.php:382
541
+ msgid "Button text"
542
+ msgstr ""
543
+
544
+ #: ../includes/settings.php:384
545
+ msgid "Refuse consent"
546
+ msgstr ""
547
+
548
+ #: ../includes/settings.php:386
549
+ msgid "Script blocking"
550
+ msgstr ""
551
+
552
+ #: ../includes/settings.php:387
553
+ msgid "Reloading"
554
+ msgstr ""
555
+
556
+ #: ../includes/settings.php:388
557
+ msgid "On scroll"
558
+ msgstr ""
559
+
560
+ #: ../includes/settings.php:389
561
+ msgid "On click"
562
+ msgstr ""
563
+
564
+ #: ../includes/settings.php:390
565
+ msgid "Accepted expiry"
566
+ msgstr ""
567
+
568
+ #: ../includes/settings.php:391
569
+ msgid "Rejected expiry"
570
+ msgstr ""
571
+
572
+ #: ../includes/settings.php:396
573
+ msgid "Notice Design"
574
+ msgstr ""
575
+
576
+ #: ../includes/settings.php:397
577
+ msgid "Position"
578
+ msgstr ""
579
+
580
+ #: ../includes/settings.php:398
581
+ msgid "Animation"
582
+ msgstr ""
583
+
584
+ #: ../includes/settings.php:399
585
+ msgid "Colors"
586
+ msgstr ""
587
+
588
+ #: ../includes/settings.php:400
589
+ msgid "Button class"
590
+ msgstr ""
591
+
592
+ #: ../includes/settings.php:412
593
+ msgid "Enable global network settings override."
594
+ msgstr ""
595
+
596
+ #: ../includes/settings.php:413
597
+ msgid "Every site in the network will use the same settings. Site administrators will not be able to change them."
598
+ msgstr ""
599
+
600
+ #: ../includes/settings.php:427
601
+ msgid "This option works only for domain-based networks."
602
+ msgstr ""
603
+
604
+ #: ../includes/settings.php:433
605
+ msgid "Enable global network cookie consent."
606
+ msgstr ""
607
+
608
+ #: ../includes/settings.php:434
609
+ msgid "Cookie consent in one of the network sites results in a consent in all of the sites on the network."
610
+ msgstr ""
611
+
612
+ #: ../includes/settings.php:445
613
+ msgid "Global network settings override is active. Every site will use the same network settings. Please contact super administrator if you want to have more control over the settings."
614
+ msgstr ""
615
+
616
+ #: ../includes/settings.php:464 ../includes/settings.php:478
617
+ #: ../includes/settings.php:497
618
+ msgid "Notice"
619
+ msgstr ""
620
+
621
+ #: ../includes/settings.php:464 ../includes/settings.php:465
622
+ #: ../includes/settings.php:466 ../includes/settings.php:467
623
+ #: ../includes/settings.php:478 ../includes/settings.php:497
624
+ msgid "Active"
625
+ msgstr ""
626
+
627
+ #: ../includes/settings.php:466 ../includes/settings.php:480
628
+ #: ../includes/settings.php:499 ../includes/welcome.php:417
629
+ msgid "Cookie Categories"
630
+ msgstr ""
631
+
632
+ #: ../includes/settings.php:467 ../includes/settings.php:481
633
+ #: ../includes/settings.php:500 ../includes/welcome.php:418
634
+ msgid "Proof-of-Consent"
635
+ msgstr ""
636
+
637
+ #: ../includes/settings.php:470
638
+ msgid "Log in & Configure"
639
+ msgstr ""
640
+
641
+ #: ../includes/settings.php:471
642
+ msgid "Log into the Cookie Compliance&trade; web application and configure your Privacy Experience."
643
+ msgstr ""
644
+
645
+ #: ../includes/settings.php:479 ../includes/settings.php:480
646
+ #: ../includes/settings.php:481
647
+ msgid "Pending"
648
+ msgstr ""
649
+
650
+ #: ../includes/settings.php:484
651
+ msgid "Log in & configure"
652
+ msgstr ""
653
+
654
+ #: ../includes/settings.php:485
655
+ msgid "Log into the Cookie Compliance&trade; web application and complete the setup process."
656
+ msgstr ""
657
+
658
+ #: ../includes/settings.php:498 ../includes/settings.php:499
659
+ #: ../includes/settings.php:500
660
+ msgid "Inactive"
661
+ msgstr ""
662
+
663
+ #: ../includes/settings.php:503
664
+ msgid "Add Compliance features"
665
+ msgstr ""
666
+
667
+ #: ../includes/settings.php:504
668
+ msgid "Sign up to Cookie Compliance&trade; and add GDPR, CCPA and other international data privacy laws compliance features."
669
+ msgstr ""
670
+
671
+ #: ../includes/settings.php:519
672
+ msgid "Enter your Cookie Compliance&trade; application ID."
673
+ msgstr ""
674
+
675
+ #: ../includes/settings.php:532
676
+ msgid "Enter your Cookie Compliance&trade; application secret key."
677
+ msgstr ""
678
+
679
+ #: ../includes/settings.php:544
680
+ msgid "Enable to automatically block 3rd party scripts before user consent."
681
+ msgstr ""
682
+
683
+ #: ../includes/settings.php:545
684
+ msgid "In case you're experiencing issues with your site disable that feature temporarily."
685
+ msgstr ""
686
+
687
+ #: ../includes/settings.php:558
688
+ msgid "Purge Cache"
689
+ msgstr ""
690
+
691
+ #: ../includes/settings.php:560
692
+ msgid "Click the Purge Cache button to refresh the app configuration."
693
+ msgstr ""
694
+
695
+ #: ../includes/settings.php:572
696
+ msgid "Enable to hide the consent banner for logged in users."
697
+ msgstr ""
698
+
699
+ #: ../includes/settings.php:584
700
+ msgid "Enable to run the consent banner in debug mode."
701
+ msgstr ""
702
+
703
+ #: ../includes/settings.php:597
704
+ msgid "Enter the cookie notice message."
705
+ msgstr ""
706
+
707
+ #: ../includes/settings.php:610
708
+ msgid "The text of the option to accept the notice and make it disappear."
709
+ msgstr ""
710
+
711
+ #: ../includes/settings.php:622
712
+ msgid "Enable to give to the user the possibility to refuse third party non functional cookies."
713
+ msgstr ""
714
+
715
+ #: ../includes/settings.php:626
716
+ msgid "The text of the button to refuse the consent."
717
+ msgstr ""
718
+
719
+ #: ../includes/settings.php:645
720
+ msgid "Head"
721
+ msgstr ""
722
+
723
+ #: ../includes/settings.php:646
724
+ msgid "Body"
725
+ msgstr ""
726
+
727
+ #: ../includes/settings.php:649
728
+ msgid "The code to be used in your site header, before the closing head tag."
729
+ msgstr ""
730
+
731
+ #: ../includes/settings.php:653
732
+ msgid "The code to be used in your site footer, before the closing body tag."
733
+ msgstr ""
734
+
735
+ #: ../includes/settings.php:657
736
+ msgid "Enter non functional cookies Javascript code here (for e.g. Google Analitycs) to be used after the notice is accepted."
737
+ msgstr ""
738
+
739
+ #: ../includes/settings.php:657
740
+ msgid "To get the user consent status use the <code>cn_cookies_accepted()</code> function."
741
+ msgstr ""
742
+
743
+ #: ../includes/settings.php:670
744
+ msgid "Enable to give to the user the possibility to revoke their consent <i>(requires \"Refuse consent\" option enabled)</i>."
745
+ msgstr ""
746
+
747
+ #: ../includes/settings.php:673
748
+ msgid "Enter the revoke message."
749
+ msgstr ""
750
+
751
+ #: ../includes/settings.php:675
752
+ msgid "The text of the button to revoke the consent."
753
+ msgstr ""
754
+
755
+ #: ../includes/settings.php:683
756
+ msgid "Select the method for displaying the revoke button - automatic (in the banner) or manual using <code>[cookies_revoke]</code> shortcode."
757
+ msgstr ""
758
+
759
+ #: ../includes/settings.php:697
760
+ msgid "Enable to reload the page after the notice is accepted."
761
+ msgstr ""
762
+
763
+ #: ../includes/settings.php:724
764
+ msgid "Enable privacy policy link."
765
+ msgstr ""
766
+
767
+ #: ../includes/settings.php:727
768
+ msgid "The text of the privacy policy button."
769
+ msgstr ""
770
+
771
+ #: ../includes/settings.php:739
772
+ msgid "Select where to redirect user for more information."
773
+ msgstr ""
774
+
775
+ #: ../includes/settings.php:742
776
+ msgid "-- select page --"
777
+ msgstr ""
778
+
779
+ #: ../includes/settings.php:753
780
+ msgid "Select from one of your site's pages."
781
+ msgstr ""
782
+
783
+ #: ../includes/settings.php:759
784
+ msgid "Synchronize with WordPress Privacy Policy page."
785
+ msgstr ""
786
+
787
+ #: ../includes/settings.php:766
788
+ msgid "Enter the full URL starting with http(s)://"
789
+ msgstr ""
790
+
791
+ #: ../includes/settings.php:811
792
+ msgid "The amount of time that the cookie should be stored for when user accepts the notice."
793
+ msgstr ""
794
+
795
+ #: ../includes/settings.php:834
796
+ msgid "The amount of time that the cookie should be stored for when the user doesn't accept the notice."
797
+ msgstr ""
798
+
799
+ #: ../includes/settings.php:853
800
+ msgid "Select where all the plugin scripts should be placed."
801
+ msgstr ""
802
+
803
+ #: ../includes/settings.php:874
804
+ msgid "Select location for the notice."
805
+ msgstr ""
806
+
807
+ #: ../includes/settings.php:895
808
+ msgid "Select the animation style."
809
+ msgstr ""
810
+
811
+ #: ../includes/settings.php:907
812
+ msgid "Enable to accept the notice when user scrolls."
813
+ msgstr ""
814
+
815
+ #: ../includes/settings.php:910
816
+ msgid "Number of pixels user has to scroll to accept the notice and make it disappear."
817
+ msgstr ""
818
+
819
+ #: ../includes/settings.php:923
820
+ msgid "Enable to accept the notice on any click on the page."
821
+ msgstr ""
822
+
823
+ #: ../includes/settings.php:935
824
+ msgid "Enable if you want all plugin data to be deleted on deactivation."
825
+ msgstr ""
826
+
827
+ #: ../includes/settings.php:948
828
+ msgid "Enter additional button CSS classes separated by spaces."
829
+ msgstr ""
830
+
831
+ #: ../includes/settings.php:974
832
+ msgid "Bar opacity"
833
+ msgstr ""
834
+
835
+ #: ../includes/settings.php:1133
836
+ msgid "Settings saved."
837
+ msgstr ""
838
+
839
+ #: ../includes/settings.php:1143
840
+ msgid "Settings restored to defaults."
841
+ msgstr ""
842
+
843
+ #: ../includes/settings.php:1238
844
+ msgid "Are you sure you want to reset these settings to defaults?"
845
+ msgstr ""
846
+
847
+ #: ../includes/welcome-api.php:33 ../includes/welcome-api.php:36
848
+ #: ../includes/welcome-api.php:39 ../includes/welcome-api.php:42
849
+ #: ../includes/welcome.php:184 ../includes/welcome.php:192
850
+ #: ../includes/welcome.php:195
851
+ msgid "You do not have permission to access this page."
852
+ msgstr ""
853
+
854
+ #: ../includes/welcome-api.php:102 ../includes/welcome-api.php:305
855
+ #: ../includes/welcome-api.php:347 ../includes/welcome-api.php:492
856
+ #: ../includes/welcome-api.php:566 ../includes/welcome-api.php:1090
857
+ #: ../includes/welcome.php:83
858
+ msgid "Unexpected error occurred. Please try again later."
859
+ msgstr ""
860
+
861
+ #: ../includes/welcome-api.php:127
862
+ msgid "Empty plan or payment method data."
863
+ msgstr ""
864
+
865
+ #: ../includes/welcome-api.php:162
866
+ msgid "Unable to create customer data."
867
+ msgstr ""
868
+
869
+ #: ../includes/welcome-api.php:211
870
+ msgid "Unable to create payment mehotd."
871
+ msgstr ""
872
+
873
+ #: ../includes/welcome-api.php:217
874
+ msgid "No payment method token."
875
+ msgstr ""
876
+
877
+ #: ../includes/welcome-api.php:248
878
+ msgid "Please accept the Terms of Service to proceed."
879
+ msgstr ""
880
+
881
+ #: ../includes/welcome-api.php:253 ../includes/welcome-api.php:464
882
+ msgid "Email is not allowed to be empty."
883
+ msgstr ""
884
+
885
+ #: ../includes/welcome-api.php:258 ../includes/welcome-api.php:469
886
+ msgid "Password is not allowed to be empty."
887
+ msgstr ""
888
+
889
+ #: ../includes/welcome-api.php:263
890
+ msgid "Passwords do not match."
891
+ msgstr ""
892
+
893
+ #: ../includes/welcome.php:84
894
+ msgid "Passed"
895
+ msgstr ""
896
+
897
+ #: ../includes/welcome.php:85
898
+ msgid "Failed"
899
+ msgstr ""
900
+
901
+ #: ../includes/welcome.php:86 ../includes/welcome.php:334
902
+ #: ../includes/welcome.php:585 ../includes/welcome.php:683
903
+ msgid "monthly"
904
+ msgstr ""
905
+
906
+ #: ../includes/welcome.php:87
907
+ msgid "yearly"
908
+ msgstr ""
909
+
910
+ #: ../includes/welcome.php:91
911
+ msgid "<em>Compliance Failed!</em>Your website does not achieve minimum viable compliance. <b><a href=\"#\" class=\"cn-sign-up\">Sign up to Cookie Compliance</a></b> to bring your site into compliance with the latest data privacy rules and regulations."
912
+ msgstr ""
913
+
914
+ #: ../includes/welcome.php:92
915
+ msgid "<em>Compliance Passed!</em>Congratulations. Your website meets minimum viable compliance."
916
+ msgstr ""
917
+
918
+ #: ../includes/welcome.php:93 ../includes/welcome.php:685
919
+ msgid "available"
920
+ msgstr ""
921
+
922
+ #: ../includes/welcome.php:94
923
+ msgid "Please fill all the required fields."
924
+ msgstr ""
925
+
926
+ #: ../includes/welcome.php:215
927
+ msgid "Cookie Compliance is a free web application that enables websites to take a proactive approach to data protection and consent laws."
928
+ msgstr ""
929
+
930
+ #: ../includes/welcome.php:221
931
+ msgid "It is the first solution to offer <b>intentional consent</b>, a new consent framework that incorporates the latest guidelines from over 100+ countries, and emerging standards from leading international organizations like the IEEE."
932
+ msgstr ""
933
+
934
+ #: ../includes/welcome.php:222
935
+ msgid "Cookie Notice includes <b>seamless integration</b> with Cookie Compliance to help your site comply with the latest updates to existing consent laws and provide a beautiful, multi-level experience to engage visitors in data privacy decisions."
936
+ msgstr ""
937
+
938
+ #: ../includes/welcome.php:226
939
+ msgid "Sign up to Cookie Compliance"
940
+ msgstr ""
941
+
942
+ #: ../includes/welcome.php:227
943
+ msgid "Skip for now"
944
+ msgstr ""
945
+
946
+ #: ../includes/welcome.php:255
947
+ msgid "Take a proactive approach to data protection and consent laws by signing up for Cookie Compliance account. Then select a limited Basic Plan for free or get one of the Professional Plans for unlimited visits, consent storage, languages and customizations."
948
+ msgstr ""
949
+
950
+ #: ../includes/welcome.php:299
951
+ msgid "Compliance Plans"
952
+ msgstr ""
953
+
954
+ #: ../includes/welcome.php:302
955
+ msgid "Monthly"
956
+ msgstr ""
957
+
958
+ #: ../includes/welcome.php:305
959
+ msgid "Yearly"
960
+ msgstr ""
961
+
962
+ #: ../includes/welcome.php:305
963
+ msgid "Save 12%"
964
+ msgstr ""
965
+
966
+ #: ../includes/welcome.php:313 ../includes/welcome.php:584
967
+ #: ../includes/welcome.php:682
968
+ msgid "Basic"
969
+ msgstr ""
970
+
971
+ #: ../includes/welcome.php:314
972
+ msgid "Free"
973
+ msgstr ""
974
+
975
+ #: ../includes/welcome.php:317 ../includes/welcome.php:346
976
+ msgid "GDPR, CCPA, ePrivacy, PECR compliance"
977
+ msgstr ""
978
+
979
+ #: ../includes/welcome.php:318 ../includes/welcome.php:347
980
+ msgid "Consent Analytics Dashboard"
981
+ msgstr ""
982
+
983
+ #: ../includes/welcome.php:319
984
+ msgid "<b>1,000</b> visits / month"
985
+ msgstr ""
986
+
987
+ #: ../includes/welcome.php:320
988
+ msgid "<b>30 days</b> consent storage"
989
+ msgstr ""
990
+
991
+ #: ../includes/welcome.php:321
992
+ msgid "<b>1 additional</b> language"
993
+ msgstr ""
994
+
995
+ #: ../includes/welcome.php:322
996
+ msgid "<b>Basic</b> Support"
997
+ msgstr ""
998
+
999
+ #: ../includes/welcome.php:325
1000
+ msgid "Start Basic"
1001
+ msgstr ""
1002
+
1003
+ #: ../includes/welcome.php:333
1004
+ msgid "Professional"
1005
+ msgstr ""
1006
+
1007
+ #: ../includes/welcome.php:335
1008
+ msgid "Recommended"
1009
+ msgstr ""
1010
+
1011
+ #: ../includes/welcome.php:337
1012
+ msgid "Pricing options"
1013
+ msgstr ""
1014
+
1015
+ #: ../includes/welcome.php:338 ../includes/welcome.php:339
1016
+ #: ../includes/welcome.php:340 ../includes/welcome.php:341
1017
+ #, php-format
1018
+ msgid "%s domain license"
1019
+ msgstr ""
1020
+
1021
+ #: ../includes/welcome.php:348
1022
+ msgid "<b>Unlimited</b> visits"
1023
+ msgstr ""
1024
+
1025
+ #: ../includes/welcome.php:349
1026
+ msgid "<b>Lifetime</b> consent storage"
1027
+ msgstr ""
1028
+
1029
+ #: ../includes/welcome.php:350
1030
+ msgid "<b>Unlimited</b> languages"
1031
+ msgstr ""
1032
+
1033
+ #: ../includes/welcome.php:351
1034
+ msgid "<b>Premium</b> Support"
1035
+ msgstr ""
1036
+
1037
+ #: ../includes/welcome.php:354
1038
+ msgid "Start Premium"
1039
+ msgstr ""
1040
+
1041
+ #: ../includes/welcome.php:360
1042
+ msgid "I don’t want to create an account now"
1043
+ msgstr ""
1044
+
1045
+ #: ../includes/welcome.php:374
1046
+ msgid "Congratulations"
1047
+ msgstr ""
1048
+
1049
+ #: ../includes/welcome.php:375
1050
+ msgid "You are now promoting privacy with Hu-manity.co"
1051
+ msgstr ""
1052
+
1053
+ #: ../includes/welcome.php:377
1054
+ msgid "Log in to your Cookie Compliance&trade; account and continue configuring your Privacy Experience."
1055
+ msgstr ""
1056
+
1057
+ #: ../includes/welcome.php:380
1058
+ msgid "Go to Application"
1059
+ msgstr ""
1060
+
1061
+ #: ../includes/welcome.php:405
1062
+ msgid "Compliance check"
1063
+ msgstr ""
1064
+
1065
+ #: ../includes/welcome.php:406
1066
+ msgid "This is a Compliance Check to determine your site’s compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws."
1067
+ msgstr ""
1068
+
1069
+ #: ../includes/welcome.php:408
1070
+ msgid "Site URL"
1071
+ msgstr ""
1072
+
1073
+ #: ../includes/welcome.php:409
1074
+ msgid "Site Name"
1075
+ msgstr ""
1076
+
1077
+ #: ../includes/welcome.php:412
1078
+ msgid "Checking..."
1079
+ msgstr ""
1080
+
1081
+ #: ../includes/welcome.php:415
1082
+ msgid "Notifies visitors that site uses cookies."
1083
+ msgstr ""
1084
+
1085
+ #: ../includes/welcome.php:416
1086
+ msgid "Non-essential cookies blocked until consent is registered."
1087
+ msgstr ""
1088
+
1089
+ #: ../includes/welcome.php:417
1090
+ msgid "Separate consent requested per purpose of use."
1091
+ msgstr ""
1092
+
1093
+ #: ../includes/welcome.php:418
1094
+ msgid "Proof-of-consent stored in secure audit format."
1095
+ msgstr ""
1096
+
1097
+ #: ../includes/welcome.php:434
1098
+ msgid "Live Setup"
1099
+ msgstr ""
1100
+
1101
+ #: ../includes/welcome.php:435
1102
+ msgid "Configure your Cookie Notice & Compliance design and compliance features through the options below. Click Apply Setup to save the configuration and go to selecting your preferred cookie solution."
1103
+ msgstr ""
1104
+
1105
+ #: ../includes/welcome.php:439
1106
+ msgid "Banner Compliance"
1107
+ msgstr ""
1108
+
1109
+ #: ../includes/welcome.php:460
1110
+ msgid "Select the laws that apply to your business"
1111
+ msgstr ""
1112
+
1113
+ #: ../includes/welcome.php:462
1114
+ msgid "GDPR"
1115
+ msgstr ""
1116
+
1117
+ #: ../includes/welcome.php:463
1118
+ msgid "CCPA"
1119
+ msgstr ""
1120
+
1121
+ #: ../includes/welcome.php:467
1122
+ msgid "Select a naming style for the consent choices"
1123
+ msgstr ""
1124
+
1125
+ #: ../includes/welcome.php:469
1126
+ msgid "Silver, Gold, Platinum (Default)​"
1127
+ msgstr ""
1128
+
1129
+ #: ../includes/welcome.php:470
1130
+ msgid "Private, Balanced, Personalized"
1131
+ msgstr ""
1132
+
1133
+ #: ../includes/welcome.php:471
1134
+ msgid "Reject All, Accept Some, Accept All​"
1135
+ msgstr ""
1136
+
1137
+ #: ../includes/welcome.php:475
1138
+ msgid "Select additional information to include in the banner:"
1139
+ msgstr ""
1140
+
1141
+ #: ../includes/welcome.php:477
1142
+ msgid "Display <b>Privacy Paper</b> to provide helpful data privacy and consent information to visitors."
1143
+ msgstr ""
1144
+
1145
+ #: ../includes/welcome.php:478
1146
+ msgid "Display <b>Privacy Contact</b> to provide Data Controller contact information and links to external data privacy resources."
1147
+ msgstr ""
1148
+
1149
+ #: ../includes/welcome.php:481 ../includes/welcome.php:509
1150
+ msgid "available for Cookie Compliance&trade; Pro plans only"
1151
+ msgstr ""
1152
+
1153
+ #: ../includes/welcome.php:485
1154
+ msgid "Banner Design"
1155
+ msgstr ""
1156
+
1157
+ #: ../includes/welcome.php:489
1158
+ msgid "Select your preferred display position"
1159
+ msgstr ""
1160
+
1161
+ #: ../includes/welcome.php:493
1162
+ msgid "Left"
1163
+ msgstr ""
1164
+
1165
+ #: ../includes/welcome.php:494
1166
+ msgid "Right"
1167
+ msgstr ""
1168
+
1169
+ #: ../includes/welcome.php:495
1170
+ msgid "Center"
1171
+ msgstr ""
1172
+
1173
+ #: ../includes/welcome.php:499
1174
+ msgid "Adjust the banner color scheme"
1175
+ msgstr ""
1176
+
1177
+ #: ../includes/welcome.php:501
1178
+ msgid "Color of the buttons and interactive elements."
1179
+ msgstr ""
1180
+
1181
+ #: ../includes/welcome.php:502
1182
+ msgid "Color of the banner background."
1183
+ msgstr ""
1184
+
1185
+ #: ../includes/welcome.php:503
1186
+ msgid "Color of the body text."
1187
+ msgstr ""
1188
+
1189
+ #: ../includes/welcome.php:504
1190
+ msgid "Color of the borders and inactive elements."
1191
+ msgstr ""
1192
+
1193
+ #: ../includes/welcome.php:505
1194
+ msgid "Color of the heading text."
1195
+ msgstr ""
1196
+
1197
+ #: ../includes/welcome.php:506
1198
+ msgid "Color of the button text."
1199
+ msgstr ""
1200
+
1201
+ #: ../includes/welcome.php:514
1202
+ msgid "Apply Setup"
1203
+ msgstr ""
1204
+
1205
+ #: ../includes/welcome.php:532
1206
+ msgid "Compliance account"
1207
+ msgstr ""
1208
+
1209
+ #: ../includes/welcome.php:534
1210
+ msgid "Create a Cookie Compliance&trade; account and select your preferred plan."
1211
+ msgstr ""
1212
+
1213
+ #: ../includes/welcome.php:538
1214
+ msgid "Create Account"
1215
+ msgstr ""
1216
+
1217
+ #: ../includes/welcome.php:543 ../includes/welcome.php:651
1218
+ msgid "Email address"
1219
+ msgstr ""
1220
+
1221
+ #: ../includes/welcome.php:546 ../includes/welcome.php:654
1222
+ msgid "Password"
1223
+ msgstr ""
1224
+
1225
+ #: ../includes/welcome.php:549
1226
+ msgid "Confirm Password"
1227
+ msgstr ""
1228
+
1229
+ #: ../includes/welcome.php:553
1230
+ #, php-format
1231
+ msgid "I have read and agree to the <a href=\"%s\" target=\"_blank\">Terms of Service"
1232
+ msgstr ""
1233
+
1234
+ #: ../includes/welcome.php:557
1235
+ msgid "Sign Up"
1236
+ msgstr ""
1237
+
1238
+ #: ../includes/welcome.php:571
1239
+ msgid "Already have an account?"
1240
+ msgstr ""
1241
+
1242
+ #: ../includes/welcome.php:571 ../includes/welcome.php:657
1243
+ msgid "Sign in"
1244
+ msgstr ""
1245
+
1246
+ #: ../includes/welcome.php:578 ../includes/welcome.php:676
1247
+ msgid "Select Plan"
1248
+ msgstr ""
1249
+
1250
+ #: ../includes/welcome.php:585 ../includes/welcome.php:683
1251
+ msgid "<b>Professional</b>"
1252
+ msgstr ""
1253
+
1254
+ #: ../includes/welcome.php:589 ../includes/welcome.php:691
1255
+ #: ../includes/welcome.php:732
1256
+ msgid "Confirm"
1257
+ msgstr ""
1258
+
1259
+ #: ../includes/welcome.php:594 ../includes/welcome.php:697
1260
+ msgid "Payment Method"
1261
+ msgstr ""
1262
+
1263
+ #: ../includes/welcome.php:596 ../includes/welcome.php:699
1264
+ msgid "Credit Card"
1265
+ msgstr ""
1266
+
1267
+ #: ../includes/welcome.php:597 ../includes/welcome.php:700
1268
+ msgid "PayPal"
1269
+ msgstr ""
1270
+
1271
+ #: ../includes/welcome.php:603 ../includes/welcome.php:706
1272
+ msgid "Card Number"
1273
+ msgstr ""
1274
+
1275
+ #: ../includes/welcome.php:607 ../includes/welcome.php:710
1276
+ msgid "Expiration Date"
1277
+ msgstr ""
1278
+
1279
+ #: ../includes/welcome.php:611 ../includes/welcome.php:714
1280
+ msgid "CVC/CVV"
1281
+ msgstr ""
1282
+
1283
+ #: ../includes/welcome.php:615 ../includes/welcome.php:718
1284
+ msgid "Submit"
1285
+ msgstr ""
1286
+
1287
+ #: ../includes/welcome.php:640
1288
+ msgid "Compliance Sign in"
1289
+ msgstr ""
1290
+
1291
+ #: ../includes/welcome.php:642
1292
+ msgid "Sign in to your existing Cookie Compliance&trade; account and select your preferred plan."
1293
+ msgstr ""
1294
+
1295
+ #: ../includes/welcome.php:646
1296
+ msgid "Account Login"
1297
+ msgstr ""
1298
+
1299
+ #: ../includes/welcome.php:671
1300
+ msgid "Don't have an account yet?"
1301
+ msgstr ""
1302
+
1303
+ #: ../includes/welcome.php:671
1304
+ msgid "Sign up"
1305
+ msgstr ""
1306
+
1307
+ #: ../includes/welcome.php:685
1308
+ msgid "Use License"
1309
+ msgstr ""
1310
+
1311
+ #: ../includes/welcome.php:728
1312
+ msgid "Select subscription"
1313
+ msgstr ""
1314
+
1315
+ #: ../includes/welcome.php:729
1316
+ msgid "Licenses"
1317
+ msgstr ""
1318
+
1319
+ #: ../includes/welcome.php:752
1320
+ msgid "Success!"
1321
+ msgstr ""
1322
+
1323
+ #: ../includes/welcome.php:753
1324
+ msgid "You have successfully upgraded your website to Cookie Compliance&trade;"
1325
+ msgstr ""
1326
+
1327
+ #: ../includes/welcome.php:753
1328
+ #, php-format
1329
+ msgid "Go to Cookie Compliance&trade; application now. Or access it anytime from your <a href=\"%s\">Cookie Notice settings page</a>."
1330
+ msgstr ""
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Cookie Notice & Compliance for GDPR / CCPA ===
2
  Contributors: humanityco
3
  Tags: gdpr, ccpa, cookies, consent, compliance
4
- Requires at least: 4.3
5
  Requires PHP: 5.4
6
- Tested up to: 6.0
7
- Stable tag: 2.3.1
8
  License: MIT License
9
  License URI: http://opensource.org/licenses/MIT
10
 
@@ -61,31 +61,31 @@ For all businesses, the resources required to stay ahead of the latest regulatio
61
 
62
  <strong>Cookie Compliance covers all current and upcoming regulations:</strong>
63
 
64
- * GDPR (EU)
65
- * ePrivacy Directive (EU)
66
  * ePrivacy Regulation (EU)
67
- * PECR (UK)
68
- * LGPD (Brazil)
69
- * PIPEDA (Canada)
70
  * PDPB (India)
71
- * CCPA (California, US)
72
  * VCDPA (Virginia, US)
73
  * Colorado Privacy Act (US)
74
  * CPRA (California, US)
75
 
76
  <strong>Cookie Compliance incorporates all recent formatting guidance:</strong>
77
 
78
- * European Data Protection Supervisor (EDPS)
79
- * ICO (United Kingdom)
80
- * CNIL (France)
81
- * GPDP (Italy)
82
- * BfDl (Germany)
83
- * AEPD (Spain)
84
- * European Center for Digital Rights (noyb.eu)
85
 
86
  <strong>Cookie Compliance targets dark patterns</strong>
87
 
88
- Dark Patterns are user interface (UI) techniques that push site visitors to make decisions (such as agreeing to the installation of cookies on their devices) that they might not otherwise make. The most common Dark Pattern is the lack of an equal “reject all” button on the first layer of the consent notice. Dark Patterns are explicitly banned under GDPR and other data protection laws.
89
 
90
  As a part of our proactive approach, Cookie Compliance is configured by default to prevent Dark Patterns through our unique Intentional Consent design.
91
 
@@ -107,7 +107,7 @@ Yes! Cookie Notice is a free software.
107
  Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website traffic.
108
 
109
  = Does the Cookie Notice make my site fully compliant with GDPR? =
110
- No. The plugin-only version DOES NOT include technical compliance features such as automatic script blocking, consent purpose categories, or consent record storage. These features are only available through the Cookie Compliance integration.
111
 
112
  = Does the Cookie Compiance integration make my site fully compliant with GDPR? =
113
  Yes! The plugin + web appliaction version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions.
@@ -121,6 +121,11 @@ Yes! The plugin + web appliaction version includes technical compliance features
121
 
122
  == Changelog ==
123
 
 
 
 
 
 
124
  = 2.3.1 =
125
  * New: Option to run consent banner in debug mode
126
  * Fix: Invalid validation of dismissable notices
@@ -139,7 +144,7 @@ Yes! The plugin + web appliaction version includes technical compliance features
139
  * Fix: Uncrawlable close notice link
140
  * Tweak: WordPress 5.9 compatibility
141
  * Tweak: Prevent displaying the notice in an iframe
142
- * Tweak: Send site language to a web app on signup
143
 
144
  = 2.2.1 =
145
  * Fix: Missing variable definition in frontend
@@ -264,7 +269,7 @@ Yes! The plugin + web appliaction version includes technical compliance features
264
 
265
  = 1.2.38 =
266
  * Tweak: Move frontend cookie js functions before the document ready call, thanks to [fgreinus](https://github.com/fgreinus)
267
- * Tweak: Adjust functional javascript code handling
268
  * Fix: Chhromium infinity expiration date not valid
269
  * Fix: Remove deprecated screen_icon() function
270
 
@@ -276,7 +281,7 @@ Yes! The plugin + web appliaction version includes technical compliance features
276
  * Fix: Repository upload issue with 1.2.36
277
 
278
  = 1.2.36 =
279
- * Fix: String translation support for WMPL 3.2+
280
  * Fix: Global var possible conflict with other plugins
281
  * Tweak: Add $options array to "cn_cookie_notice_output" filter, thanks to [chesio](https://github.com/chesio).
282
  * Tweak: Removed local translation files in favor of WP repository translations.
@@ -352,7 +357,7 @@ Yes! The plugin + web appliaction version includes technical compliance features
352
  * New: Hebrew translation, thanks to [Ahrale Shrem](http://atar4u.com/)
353
 
354
  = 1.2.16 =
355
- * Tweak: Dutch translation missing due to a typo
356
 
357
  = 1.2.15 =
358
  * New: Danish translation, thanks to Hans C. Jorgensen
@@ -423,6 +428,5 @@ Initial release
423
 
424
  == Upgrade Notice ==
425
 
426
- = 2.3.1 =
427
- * New: Option to run consent banner in debug mode
428
- * Fix: Invalid validation of dismissable notices
1
  === Cookie Notice & Compliance for GDPR / CCPA ===
2
  Contributors: humanityco
3
  Tags: gdpr, ccpa, cookies, consent, compliance
4
+ Requires at least: 4.7
5
  Requires PHP: 5.4
6
+ Tested up to: 6.0.1
7
+ Stable tag: 2.4.0
8
  License: MIT License
9
  License URI: http://opensource.org/licenses/MIT
10
 
61
 
62
  <strong>Cookie Compliance covers all current and upcoming regulations:</strong>
63
 
64
+ * GDPR (EU)
65
+ * ePrivacy Directive (EU)
66
  * ePrivacy Regulation (EU)
67
+ * PECR (UK)
68
+ * LGPD (Brazil)
69
+ * PIPEDA (Canada)
70
  * PDPB (India)
71
+ * CCPA (California, US)
72
  * VCDPA (Virginia, US)
73
  * Colorado Privacy Act (US)
74
  * CPRA (California, US)
75
 
76
  <strong>Cookie Compliance incorporates all recent formatting guidance:</strong>
77
 
78
+ * European Data Protection Supervisor (EDPS)
79
+ * ICO (United Kingdom)
80
+ * CNIL (France)
81
+ * GPDP (Italy)
82
+ * BfDl (Germany)
83
+ * AEPD (Spain)
84
+ * European Center for Digital Rights (noyb.eu)
85
 
86
  <strong>Cookie Compliance targets dark patterns</strong>
87
 
88
+ Dark Patterns are user interface (UI) techniques that push site visitors to make decisions (such as agreeing to the installation of cookies on their devices) that they might not otherwise make. The most common Dark Pattern is the lack of an equal “reject all” button on the first layer of the consent notice. Dark Patterns are explicitly banned under GDPR and other data protection laws.
89
 
90
  As a part of our proactive approach, Cookie Compliance is configured by default to prevent Dark Patterns through our unique Intentional Consent design.
91
 
107
  Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website traffic.
108
 
109
  = Does the Cookie Notice make my site fully compliant with GDPR? =
110
+ No. The plugin-only version DOES NOT include technical compliance features such as automatic script blocking, consent purpose categories, or consent record storage. These features are only available through the Cookie Compliance integration.
111
 
112
  = Does the Cookie Compiance integration make my site fully compliant with GDPR? =
113
  Yes! The plugin + web appliaction version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions.
121
 
122
  == Changelog ==
123
 
124
+ = 2.4.0 =
125
+ * New: Advanced Multisite support
126
+ * Fix: Polylang translation not working for shortcode
127
+ * Fix: Parse error: syntax error, unexpected ‘[‘
128
+
129
  = 2.3.1 =
130
  * New: Option to run consent banner in debug mode
131
  * Fix: Invalid validation of dismissable notices
144
  * Fix: Uncrawlable close notice link
145
  * Tweak: WordPress 5.9 compatibility
146
  * Tweak: Prevent displaying the notice in an iframe
147
+ * Tweak: Send site language to a web app on signup
148
 
149
  = 2.2.1 =
150
  * Fix: Missing variable definition in frontend
269
 
270
  = 1.2.38 =
271
  * Tweak: Move frontend cookie js functions before the document ready call, thanks to [fgreinus](https://github.com/fgreinus)
272
+ * Tweak: Adjust functional javascript code handling
273
  * Fix: Chhromium infinity expiration date not valid
274
  * Fix: Remove deprecated screen_icon() function
275
 
281
  * Fix: Repository upload issue with 1.2.36
282
 
283
  = 1.2.36 =
284
+ * Fix: String translation support for WMPL 3.2+
285
  * Fix: Global var possible conflict with other plugins
286
  * Tweak: Add $options array to "cn_cookie_notice_output" filter, thanks to [chesio](https://github.com/chesio).
287
  * Tweak: Removed local translation files in favor of WP repository translations.
357
  * New: Hebrew translation, thanks to [Ahrale Shrem](http://atar4u.com/)
358
 
359
  = 1.2.16 =
360
+ * Tweak: Dutch translation missing due to a typo
361
 
362
  = 1.2.15 =
363
  * New: Danish translation, thanks to Hans C. Jorgensen
428
 
429
  == Upgrade Notice ==
430
 
431
+ = 2.4.0 =
432
+ * New: Advanced Multisite support