GIF89a=( õ' 7IAXKgNgYvYx\%wh…hŽth%ˆs%—x¨}9®Œ©€&©‰%¶†(¹–.¹5·œD¹&Çš)ÇŸ5ǘ;Í£*È¡&Õ²)ׯ7×µ<Ñ»4ï°3ø‘HÖ§KͯT÷¨Yÿšqÿ»qÿÔFØ !ù ' !ÿ NETSCAPE2.0 , =( þÀ“pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§gª«ªE¯°¨¬ª±²Œ¹º¹E¾­”´ÂB¶¯ §Åȸ»ÑD¾¿Á•ÄÅ®° ÝH¾ÒLÀÆDÙ«D¶BÝïðÀ¾DÑÑÔTÌÍíH òGö¨A RÎڐ |¥ ٭&ºìE8œ¹kGÔAÞpx­a¶­ã R2XB®åE8I€Õ6Xî:vT)äžþÀq¦è³¥ì仕F~%xñ  4#ZÔ‰O|-4Bs‘X:= QÉ œš lºÒyXJŠGȦ|s hÏíK–3l7·B|¥$'7Jީܪ‰‡àá”Dæn=Pƒ ¤Òëí‰`䌨ljóá¯Éüv>á–Á¼5 ½.69ûϸd«­ºÀûnlv©‹ªîf{¬ÜãPbŸ  l5‘ޝpß ´ ˜3aÅùäI«O’ý·‘áÞ‡˜¾Æ‚ÙÏiÇÿ‹Àƒ #öó)pâš Þ½ ‘Ý{ó)vmÞü%D~ 6f s}ŃƒDØW Eþ`‡þ À…L8xá†ç˜{)x`X/> Ì}mø‚–RØ‘*|`D=‚Ø_ ^ð5 !_…'aä“OÚ—7âcð`D”Cx`ÝÂ¥ä‹éY¹—F¼¤¥Š?¡Õ™ n@`} lď’ÄÉ@4>ñd œ à‘vÒxNÃ×™@žd=ˆgsžG±æ ´²æud &p8Qñ)ˆ«lXD©øÜéAžHìySun jª×k*D¤LH] †¦§C™Jä–´Xb~ʪwStŽ6K,°£qÁœ:9ت:¨þªl¨@¡`‚ûÚ ».Û¬¯t‹ÆSÉ[:°=Š‹„‘Nåû”Ìî{¿ÂA ‡Rà›ÀÙ6úë°Ÿð0Ä_ ½;ÃϱîÉì^ÇÛÇ#Ëë¼ôº!±Ä˜íUîÅÇ;0L1óÁµö«p% AÀºU̬ݵ¼á%霼€‡¯Á~`ÏG¯»À× ­²± =4ªnpð3¾¤³¯­ü¾¦îuÙuµÙ®|%2ÊIÿür¦#0·ÔJ``8È@S@5ê¢ ö×Þ^`8EÜ]ý.뜃Âç 7 ú ȉÞj œ½Dç zý¸iþœÑÙûÄë!ˆÞÀl§Ïw‹*DçI€nEX¯¬¼ &A¬Go¼QföõFç°¯;é¦÷îŽêJ°îúôF5¡ÌQ|îúöXªæ»TÁÏyñêï]ê² o óÎC=öõ›ÒÓPB@ D×½œä(>èCÂxŽ`±«Ÿ–JЀ»Û á¤±p+eE0`ëŽ`A Ú/NE€Ø†À9‚@¤à H½7”à‡%B‰`Àl*ƒó‘–‡8 2ñ%¸ —€:Ù1Á‰E¸àux%nP1ð!‘ðC)¾P81lÑɸF#ˆ€{´âé°ÈB„0>±û °b¡Š´±O‚3È–Ù()yRpbµ¨E.Z‘D8ÊH@% òŒx+%Ù˜Æcü »¸˜fõ¬b·d`Fê™8èXH"ÉÈ-±|1Ô6iI, 2““¬$+](A*jÐ QTÂo‰.ÛU슬Œã„Ž`¯SN¡–¶Äåyše¯ª’­¬‚´b¦Éož œ)åyâ@Ì®3 ÎtT̉°&Ø+žLÀf"Ø-|žçÔ>‡Ðv¦Ðžì\‚ Q1)Ž@Žh#aP72”ˆ™¨$‚ !ù " , =( …7IAXG]KgNgYvYxR"k\%w]'}hŽth%ˆg+ˆs%—r.—m3šx3˜x¨}9®€&©€+¨‡7§‰%¶†(¹–.¹œD¹&ǘ;Í•&ײ)×»4ïÌ6ò§KÍ þ@‘pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§g «¬ E ±± ¨­¶°ººE Á´”·®C¬²§Ç¶Œ»ÓDÃÕƷ¯Ê±H½ºM×ÁGÚ¬D¶BËÁ½î½DÓôTÏÛßîG»ôõC×CÌ l&âž:'òtU³6ɹ#·Ø)€'Ü.6±&ëÍÈ» K(8p0N?!æ2"ÛˆNIJX>R¼ÐO‚M '¡¨2¸*Ÿþ>#n↠å@‚<[:¡Iïf’ ¤TÚ˘CdbÜÙ“[«ŽEú5MBo¤×@€`@„€Êt W-3 ¶Ÿ¡BíêäjIÝ…Eò9[T…$íêﯧ„…•s»Óȳ¹€ÅÚdc®UUρ#±Ùïldj?´í¼²`\ŽÁðÞu|3'ÖŒ]ë6 ¶S#²‡˜FKLÈ *N E´‘áäŠ$˜›eÄYD„ºq«.è촁ƒs \-ÔjA 9²õ÷å- üúM[Âx(ís÷ì®x€|í¡Ù’p¦‚ ŽkÛTÇDpE@WÜ ²Ç]kŠ1¨ þ€·Yb ÓÁ‰l°*n0 ç™—žzBdОu¾7ĉBl€â‰-ºx~|UåU‰  h*Hœ|e"#"?vpÄiŠe6^ˆ„+qâŠm8 #VÇá ‘å–ÄV„œ|Аè•m"сœn|@›U¶ÆÎž—Špb¥G¨ED”€±Úê2FÌIç? >Éxå Œ± ¡¤„%‘žjŸ‘ꄯ<Ìaà9ijÐ2˜D¦È&›†Z`‚å]wþ¼Â:ç6àB¤7eFJ|õÒ§Õ,¨äàFÇ®cS·Ê¶+B°,‘Þ˜ºNûãØ>PADÌHD¹æž«ÄÀnÌ¥}­#Ë’ë QÀÉSÌÂÇ2ÌXÀ{æk²lQÁ2«ÊðÀ¯w|2Í h‹ÄÂG€,m¾¶ë3ÐÙ6-´ÅE¬L°ÆIij*K½ÀÇqï`DwVÍQXœÚÔpeœ±¬Ñ q˜§Tœ½µƒ°Œìu Â<¶aØ*At¯lmEØ ü ôÛN[P1ÔÛ¦­±$ÜÆ@`ùåDpy¶yXvCAyåB`ŽD¶ 0QwG#¯ æš[^Äþ $ÀÓÝǦ{„L™[±úKÄgÌ;ï£S~¹ìGX.ôgoT.»åˆ°ùŸûù¡?1zö¦Ÿž:ÅgÁ|ìL¹ „®£œŠ‚à0œ]PÁ^p F<"•ç?!,ñ‡N4—…PÄ Á„ö¨Û:Tè@hÀ‹%táÿ:ø-žI<`þ‹p I….)^ 40D#p@ƒj4–؀:²‰1Øâr˜¼F2oW¼#Z†;$Q q” ‘ ÂK¦ñNl#29 !’F@¥Bh·ᏀL!—XFóLH‘Kh¤.«hE&JòG¨¥<™WN!€ÑÙÚˆY„@†>Œž19J" 2,/ &.GXB%ÌRÈ9B6¹W]’î×ÔW¥’IÎ$ ñ‹ÓŒE8YÆ ¼³™ñA5“à®Q.aŸB€&Ø©³ JÁ—! ¦t)K%tœ-¦JF bòNMxLôþ)ÐR¸Ð™‘ èÝ6‘O!THÌ„HÛ ‰ !ù ) , =( …AXKgNgYvYxR"k\%wh…hŽh%ˆg+ˆs%—r.—x3˜x¨}9®€&©€+¨Œ,©‡7§‰%¶†(¹–.¹5·&Çš)ǘ;Í•&×£*Ȳ)ׯ7×»4ï°3øÌ6ò‘HÖ§KÍ»Hó¯T÷¨Yÿ»qÿÇhÿ þÀ”pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§g ª« E$±²¨ª­ · °²½$E$ÂÕ««D· Í ¿¦Ç¶¸ÌŒ¾³CÃÅÆ E ééH½MÛÂGâªD­ çBêêϾD²ÒaÀà€Š1r­ðÓ¤ ÔožzU!L˜C'¾yW½UGtäÇïÙllê0×àÂuGþ)AÀs[þ·xì ÁxO%ƒûX2ó—  P£n›R/¡ÑšHše+êDm?# —‘Ç£6¡8íJ¡ŸâDiäªM¥Ö„ôj“¬¹£5oQ7°- <‡ *´lãÓŒ2r/a!l)dÈ A™ÈE¢ôÔ͆…ð ;Ö˜c ¡%ß‚’Ùˆâ¸b½—pe~C"BíëÚHïeF2§æŠ8qb t_`urŠeü wÅu3êæPv§h•"ß`íÍxçLĹÜÖ3á  ~Öº“®›¸ÏMDfJÙ °„ÛµáWõ%§œ‚à©–‚X ÓØ)@®Ñ›Eþ´wëuÅSxb8y\mÖzœ¥§ZbºE—ÂLªÌw!y(>¡™wú=Ç|ÅÝs¢d €CÁW)HÜcC$€L Ä7„r.á\{)@ð` @ äXÈ$PD” `šaG:§æˆOˆ72EÐamn]ù"ŒcÊxÑŒ° &dR8`g«iÙŸLR!¦P …d’ä¡“¦ðÎTƒ¦ià|À _ ¥ Qi#¦Šg›Æ ›noMµ ›V ã£)p ç£ÎW…š=Âeªk§†j„ ´®1ß²sÉxéW«jšl|0¯B0Û, \jÛ´›6±¬¶C ÛíWþï|ëÙ‹¸ñzĸV {ì;Ýñn¼òVˆm³I¼³.Ðã¤PN¥ ²µ¼„µCã+¹ÍByî£Ñ¾HŸ›ëê 7ìYÆFTk¨SaoaY$Dµœìï¿Ã29RÈkt Çïfñ ÇÒ:ÀÐSp¹3ÇI¨â¥DZÄ ü9Ïýögñ½­uÔ*3)O‘˜Ö[_hv ,àî×Et Ÿé¶BH€ Õ[ü±64M@ÔSÌM7dÐl5-ÄÙU܍´©zߌ3Ô€3ž„ „ ¶ÛPô½5×g› êÚ˜kN„Ý…0Îj4€Ìë°“#{þÕ3S2çKÜ'ợlø¼Ú2K{° {Û¶?žm𸧠ËI¼nEò='êüóºè^üæÃ_Û=°óž‚ì#Oý¿Í'¡½áo..ÏYìnüñCœO±Áa¿¢Kô½o,üÄËbö²çºíï{ËC Ú— "”Ï{ËK ÍÒw„õ±Oz dÕ¨à:$ ƒô—«v»] A#ð «€¿šéz)Rx׿ˆ¥‚d``èw-îyÏf×K!ð€þ­Ð|ìPľ„=Ì`ý(f” 'Pa ¥ÐBJa%Ðâf§„%Š¡}FàáÝ×6>ÉäŠG"éŽè=ø!oа^FP¼Ø©Q„ÀCÙÁ`(Ž\ÄÝ® ©Â$<n@dÄ E#ììUÒI! ‚#lù‹`k¦ÐÇ'Rró’ZýNBÈMF Í[¤+‹ðɈ-áwj¨¥þ8¾rá ,VÂh„"|½œ=×G_¦Ñ™EØ 0i*%̲˜Æda0mV‚k¾)›;„&6 p>ÓjK “¦Ç# âDÂ:ûc?:R Ó¬fÞéI-Ì“•Ã<ä=™Ï7˜3œ¨˜c2ŒW ,ˆ”8(T™P‰F¡Jhç"‚ ; 403WebShell
403Webshell
Server IP : 172.67.177.218  /  Your IP : 216.73.216.165
Web Server : LiteSpeed
System : Linux premium229.web-hosting.com 4.18.0-553.45.1.lve.el8.x86_64 #1 SMP Wed Mar 26 12:08:09 UTC 2025 x86_64
User : akhalid ( 749)
PHP Version : 8.3.22
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/akhalid/dangroup.sa/wp-content/plugins/wp-statistics/assets/dev/javascript/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/akhalid/dangroup.sa/wp-content/plugins/wp-statistics/assets/dev/javascript/chart.js
wps_js.hex_to_rgba = function (hex, opacity) {
    const defaultColor = '#3288D7';
    if (typeof hex !== 'string' || hex[0] !== '#' || (hex.length !== 7 && hex.length !== 4)) {
        hex = defaultColor;
    }
    if (hex.length === 4) {
        hex = '#' + hex[1].repeat(2) + hex[2].repeat(2) + hex[3].repeat(2);
    }
    hex = hex.replace('#', '');
    let hex_to_rgba_r = parseInt(hex.substring(0, 2), 16);
    let hex_to_rgba_g = parseInt(hex.substring(2, 4), 16);
    let hex_to_rgba_b = parseInt(hex.substring(4, 6), 16);
    return wps_js.rgba_to_hex(hex_to_rgba_r, hex_to_rgba_g, hex_to_rgba_b, opacity);
}

wps_js.rgba_to_hex = function (r, g, b, a) {
    let hex_r = r.toString(16).padStart(2, '0');
    let hex_g = g.toString(16).padStart(2, '0');
    let hex_b = b.toString(16).padStart(2, '0');
    let hex_a = Math.round(a * 255).toString(16).padStart(2, '0');
    return `#${hex_r}${hex_g}${hex_b}${hex_a}`;
}

const wpsBuildTicks = (scale) => {
    const ticks = scale.getTicks();
    if (ticks.length > scale.options.ticks.maxTicksLimit) {
        const range = scale.max - scale.min;
        const desiredTicks = scale.options.ticks.maxTicksLimit || 1000;
        let stepSize = Math.ceil(range / desiredTicks);
        scale.options.ticks.stepSize = Math.max(1, stepSize);
    } else if (!scale.options.ticks.stepSize || scale.options.ticks.stepSize < 1) {
        scale.options.ticks.stepSize = 1;
    }
}

const chartColors = {
    'total': '#27A765', 'views': '#7362BF', 'visitors': '#3288D7', 'user-visitors': '#3288D7', 'anonymous-visitors': '#7362BF', 'published': '#8AC3D0','published-contents': '#8AC3D0', 'published-products': '#8AC3D0',
    'published-pages': '#8AC3D0', 'published-posts': '#8AC3D0', 'posts': '#8AC3D0' , downloads: '#3288D7', 'clicks': '#3288D7', 'Other1': '#3288D7', 'Other2': '#7362BF', 'Other3': '#8AC3D0'
};

const chartTensionValues = [0.1, 0.3, 0.5, 0.7];

const getOrCreateTooltip = (chart) => {
    let tooltipEl = chart.canvas.parentNode.querySelector('div');
    if (!tooltipEl) {
        tooltipEl = document.createElement('div');
        tooltipEl.classList.add('wps-chart-tooltip');
        tooltipEl.style.opacity = 1;
        tooltipEl.style.pointerEvents = 'none';
        tooltipEl.style.position = 'absolute';
        tooltipEl.style.transition = 'all .1s ease';
        const table = document.createElement('table');
        table.style.margin = '0px';
        tooltipEl.appendChild(table);
        chart.canvas.parentNode.appendChild(tooltipEl);
    }
    return tooltipEl;
};

wps_js.setTooltipPosition = function (tooltipEl, chart, tooltip) {
    const {
        offsetLeft: chartLeft,
        offsetTop: chartTop,
        clientWidth: chartWidth,
        clientHeight: chartHeight
    } = chart.canvas;
    const {caretX, caretY} = tooltip;

    const tooltipWidth = tooltipEl.offsetWidth;
    const tooltipHeight = tooltipEl.offsetHeight;

    const margin = 16;
    let tooltipX = chartLeft + caretX + margin;
    let tooltipY = chartTop + caretY - tooltipHeight / 2;

    if (tooltipX + tooltipWidth + margin > chartLeft + chartWidth) {
        tooltipX = chartLeft + caretX - tooltipWidth - margin;
    }

    if (tooltipX < chartLeft + margin) {
        tooltipX = chartLeft + margin;
    }

    if (tooltipY < chartTop + margin) {
        tooltipY = chartTop + margin;
    }
    if (tooltipY + tooltipHeight + margin > chartTop + chartHeight) {
        tooltipY = chartTop + chartHeight - tooltipHeight - margin;
    }
    tooltipEl.style.opacity = 1;
    tooltipEl.style.left = tooltipX + 'px';
    tooltipEl.style.top = tooltipY + 'px';
}

const externalTooltipHandler = (context, data, dateLabels, prevDateLabels, monthTooltip, prevMonthTooltip) => {
    const {chart, tooltip} = context;
    const unitTime = chart.options.plugins.tooltip.unitTime;
    const tooltipEl = getOrCreateTooltip(chart);
    if (tooltip.opacity === 0) {
        tooltipEl.style.opacity = 0;
        return;
    }
    if (tooltip.body) {
        const titleLines = tooltip.title || [];
        const dataIndex = tooltip.dataPoints[0].dataIndex;
        const datasets = chart.data.datasets;
        let innerHtml = `<div>`;
        titleLines.forEach(title => {
            if (unitTime === 'day') {
                const label = (data.data) ? data.data.labels[dataIndex] : data.labels[dataIndex];
                const {date, day} = label; // Ensure `date` and `day` are correctly extracted
                const phpDateFormat = wps_js.isset(wps_js.global, 'options', 'wp_date_format') ? wps_js.global['options']['wp_date_format'] : 'MM/DD/YYYY';
                let momentDateFormat = phpToMomentFormat(phpDateFormat);
                innerHtml += `<div class="chart-title">${moment(date).format(momentDateFormat)} (${day})</div>`;
            } else if (unitTime === 'month') {
                innerHtml += `<div class="chart-title">${monthTooltip[dataIndex]}</div>`;
            } else {
                innerHtml += `<div class="chart-title">${dateLabels[dataIndex]}</div>`;
            }
        });

        datasets.forEach((dataset, index) => {
            const meta = chart.getDatasetMeta(index);
            const isPrevious = dataset.label.includes('(Previous)');
            if (!meta.hidden && !isPrevious) {
                const value = dataset.data[dataIndex];
                innerHtml += `
                <div class="current-data">
                    <div>
                        <span class="current-data__color" style="background-color: ${dataset.hoverPointBackgroundColor};"></span>
                        ${dataset.label}
                    </div>
                    <span class="current-data__value">${value.toLocaleString()}</span>
                </div>`;
            }

            const previousDataset = datasets.find(ds => ds.label === `${dataset.label} (Previous)`);
            if (previousDataset) {
                const previousMeta = chart.getDatasetMeta(datasets.indexOf(previousDataset));
                const previousPeriodElement = document.querySelector('.wps-postbox-chart--previousPeriod');
                const isPreviousHidden = previousPeriodElement && previousPeriodElement.classList.contains('wps-line-through');

                if (!previousMeta.hidden && !isPreviousHidden) {
                    const previousValue = previousDataset.data[dataIndex] || 0;
                    let previousLabel = null;
                    if (unitTime === 'day') {
                        previousLabel = prevDateLabels[dataIndex];
                    } else if (unitTime === 'month') {
                        previousLabel = prevMonthTooltip[dataIndex];
                    } else {
                        previousLabel = prevDateLabels[dataIndex];
                    }

                    if (previousLabel === undefined) {
                        previousLabel = 'N/A'; // Fallback for undefined labels
                    }
                    innerHtml += `
                    <div class="previous-data">
                        <div>
                            <span class="previous-data__colors">
                                <span class="previous-data__color" style="background-color: ${dataset.hoverPointBackgroundColor};"></span>
                                <span class="previous-data__color" style="background-color: ${dataset.hoverPointBackgroundColor};"></span>
                            </span>
                            ${previousLabel}
                        </div>
                        <span class="previous-data__value"> ${previousValue.toLocaleString()}</span>
                    </div>`;
                }
            }
        });

        innerHtml += `</div>`;
        tooltipEl.innerHTML = innerHtml;
        wps_js.setTooltipPosition(tooltipEl, chart, tooltip);
    }
};

// Custom plugin definition
const drawVerticalLinePlugin = {
    id: 'drawVerticalLine',
    beforeDatasetDraw(chart) {
        const {ctx, scales: {x, y}, tooltip, chartArea: {top, bottom}} = chart;
        if (tooltip && tooltip._active && tooltip._active.length) {
            const xValue = tooltip._active[0].element.x;
            ctx.beginPath();
            ctx.strokeStyle = '#A9AAAE';
            ctx.lineWidth = 1;
            ctx.setLineDash([6, 6]);
            ctx.moveTo(xValue, top);
            ctx.lineTo(xValue, bottom);
            ctx.stroke();
            ctx.setLineDash([]);
        }
    }
};

const phpToMomentFormat = (phpFormat) => {
    const formatMap = {
        'd': 'DD',
        'j': 'D',
        'S': 'Do',
        'n': 'M',
        'm': 'MM',
        'F': 'MMM',
        'M': 'MMM',
        'y': 'YY',
        'Y': 'YYYY'
    };
    return phpFormat.replace(/([a-zA-Z])/g, (match) => formatMap[match] || match);
}

const formatDateRange = (startDate, endDate, unit, momentDateFormat, isInsideDashboardWidgets) => {
    const startDateFormat = momentDateFormat.replace(/,?\s?(YYYY|YY)[-/\s]?,?|[-/\s]?(YYYY|YY)[-/\s]?,?/g, "");
    if (unit === 'month') {
        const monthFormat = momentDateFormat
            .replace(/D+/g, '')
            .replace(/\/\//g, '/')
            .replace(/^\//, '')
            .replace(/\/$/, '')
            .replace(/\s*,/, '')
            .replace(/-$/, '')
            .trim();
        return moment(startDate).format(monthFormat);
    } else {
        if (moment(startDate).year() === moment(endDate).year()) {
            return `${moment(startDate).format(startDateFormat)} to ${moment(endDate).format(momentDateFormat)}`;
        } else {
            return `${moment(startDate).format(momentDateFormat)} to ${moment(endDate).format(momentDateFormat)}`;
        }
    }
}

const setMonthDateRange = (startDate, endDate, momentDateFormat) => {
    const startDateFormat = momentDateFormat.replace(/,?\s?(YYYY|YY)[-/\s]?,?|[-/\s]?(YYYY|YY)[-/\s]?,?/g, "");
    if (moment(startDate).year() === moment(endDate).year()) {
        return `${moment(startDate).format(startDateFormat)} to ${moment(endDate).format(momentDateFormat)}`;
    } else {
        return `${moment(startDate).format(momentDateFormat)} to ${moment(endDate).format(momentDateFormat)}`;
    }
}

const aggregateData = (labels, datasets, unit, momentDateFormat, isInsideDashboardWidgets) => {
    if (!labels || !labels.length || !datasets || !datasets.length) {
        console.error("Invalid input: labels or datasets are empty.");
        return {
            aggregatedLabels: [],
            aggregatedData: datasets ? datasets.map(() => []) : [],
            monthTooltipTitle: [],
        };
    }
    const isIncompletePeriod = [];
    const now = moment();
    if (unit === 'day') {
        labels.forEach(label => {
            const date = moment(label.date);
            isIncompletePeriod.push(date.isSameOrAfter(now, 'day'));
        });
        return {
            aggregatedLabels: labels.map(label => label.formatted_date),
            aggregatedData: datasets.map(dataset => dataset.data),
            monthTooltipTitle: [],
            isIncompletePeriod
        };
    }

    const aggregatedLabels = [];
    const aggregatedData = datasets.map(() => []);
    const monthTooltipTitle = [];
    const groupedData = {};

    if (unit === 'week') {
        if (wps_js._('start_of_week')) {
            moment.updateLocale('en', {
                week: {
                    dow: parseInt(wps_js._('start_of_week'))
                }
            });
        }

        const startDate = moment(labels[0].date);
        const endDate = moment(labels[labels.length - 1].date);

        // Create an array of all weeks between start and end date
        const weeks = [];
        let currentWeekStart = startDate.clone();

        while (currentWeekStart.isSameOrBefore(endDate)) {
            let nextWeekStart = currentWeekStart.clone().startOf('week').add(1, 'week');
            let weekEnd = nextWeekStart.clone().subtract(1, 'day');

            // For the last week, if it would go beyond endDate, adjust it
            if (weekEnd.isAfter(endDate)) {
                weekEnd = endDate.clone();
            }

            weeks.push({
                start: currentWeekStart.clone(),
                end: weekEnd,
                key: currentWeekStart.format('YYYY-[W]WW'),
                data: new Array(datasets.length).fill(0)
            });

            // Move to next week's start
            currentWeekStart = nextWeekStart;
        }

        labels.forEach((label, i) => {
            if (label.date) { // Check if label.date is valid
                const date = moment(label.date);
                for (let week of weeks) {
                    if (date.isBetween(week.start, week.end, 'day', '[]')) {
                        datasets.forEach((dataset, datasetIndex) => {
                            week.data[datasetIndex] += dataset.data[i] || 0;
                        });
                        break;
                    }
                }
            }
        });

        // Build the output arrays
        weeks.forEach(week => {
            const label = formatDateRange(week.start, week.end, unit, momentDateFormat, isInsideDashboardWidgets);
            aggregatedLabels.push(label);
            monthTooltipTitle.push(setMonthDateRange(week.start, week.end, momentDateFormat));
            week.data.forEach((total, datasetIndex) => {
                if (!aggregatedData[datasetIndex]) {
                    aggregatedData[datasetIndex] = [];
                }
                aggregatedData[datasetIndex].push(total);
            });
        });

        weeks.forEach(week => {
            const isIncomplete = week.end.isSameOrAfter(moment(), 'day');
            isIncompletePeriod.push(isIncomplete);
        });
    } else if (unit === 'month') {
        const startDate = moment(labels[0].date);
        const endDate = moment(labels[labels.length - 1].date);
        let currentDate = startDate.clone();
        while (currentDate.isSameOrBefore(endDate, 'month')) {
            const monthKey = currentDate.format('YYYY-MM');
            if (!groupedData[monthKey]) {
                groupedData[monthKey] = {
                    startDate: currentDate.clone().startOf('month'),
                    endDate: currentDate.clone().endOf('month'),
                    indices: [],
                };
            }
            currentDate.add(1, 'month');
        }
        labels.forEach((label, i) => {
            if (label.date) {
                const date = moment(label.date);
                const monthKey = date.format('YYYY-MM');
                if (groupedData[monthKey]) {
                    groupedData[monthKey].indices.push(i);
                }
            }
        });

        Object.keys(groupedData).forEach(monthKey => {
            const {startDate, endDate, indices} = groupedData[monthKey];
            const actualStartDate = moment.max(startDate, moment(labels[0].date));
            const actualEndDate = moment.min(endDate, moment(labels[labels.length - 1].date));
            if (!actualStartDate.isValid() || !actualEndDate.isValid()) {
                console.error(`Invalid date range for monthKey ${monthKey}`);
                return;
            }
            if (indices.length > 0) {
                const label = formatDateRange(actualStartDate, actualEndDate, unit, momentDateFormat, isInsideDashboardWidgets);
                aggregatedLabels.push(label);
                datasets.forEach((dataset, idx) => {
                    const total = indices.reduce((sum, i) => sum + (dataset.data[i] || 0), 0);
                    aggregatedData[idx].push(total);
                });
                monthTooltipTitle.push(setMonthDateRange(actualStartDate, actualEndDate, momentDateFormat));
            }
        });

        Object.keys(groupedData).forEach(monthKey => {
            const isIncomplete = groupedData[monthKey].endDate.isSameOrAfter(moment(), 'day');
            isIncompletePeriod.push(isIncomplete);
        });
    }

    return {aggregatedLabels, aggregatedData, monthTooltipTitle, isIncompletePeriod};
}

const sortTotal = (datasets) => {
    datasets.sort((a, b) => {
        if (a.slug === 'total') return -1;
        if (b.slug === 'total') return 1;
        if (a.slug === 'total-previous') return -1;
        if (b.slug === 'total-previous') return 1;
        return 0;
    });
}

const updateLegend = (lineChart, datasets, tag_id, data) => {
    const chartElement = document.getElementById(tag_id);
    const legendContainer = chartElement.parentElement.parentElement.querySelector('.wps-postbox-chart--items');

    if (legendContainer) {
        legendContainer.innerHTML = '';
        const previousPeriod = chartElement.parentElement.parentElement.querySelector('.wps-postbox-chart--previousPeriod');
        if (previousPeriod) {
            let foundPrevious = datasets.some(dataset => dataset.label.includes('(Previous)'));

            if (foundPrevious) {
                previousPeriod.style.display = 'flex';
                previousPeriod.style.cursor = 'pointer';
                if (previousPeriod._clickHandler) {
                    previousPeriod.removeEventListener('click', previousPeriod._clickHandler);
                }
                previousPeriod._clickHandler = function (e) {
                    e.stopPropagation();
                    const isPreviousHidden = previousPeriod.classList.contains('wps-line-through');
                    previousPeriod.classList.toggle('wps-line-through');

                    datasets.forEach((dataset, datasetIndex) => {
                        if (dataset.label.includes('(Previous)')) {
                            const meta = lineChart.getDatasetMeta(datasetIndex);
                            meta.hidden = !isPreviousHidden;
                        }
                    });

                    const previousDataElements = legendContainer.querySelectorAll('.previous-data');
                    previousDataElements.forEach(elem => {
                        if (isPreviousHidden) {
                            elem.classList.remove('wps-line-through');
                        } else {
                            elem.classList.add('wps-line-through');
                        }
                    });

                    lineChart.update();
                };
                previousPeriod.addEventListener('click', previousPeriod._clickHandler);
            }
        }
        datasets.forEach((dataset, index) => {
            const isPrevious = dataset.label.includes('(Previous)');
            if (!isPrevious) {
                const currentData = dataset.data.reduce((a, b) => Number(a) + Number(b), 0);
                let previousData = null;
                let previousDatasetIndex = null;
                if (data?.previousData?.datasets.length > 0) {
                    const previousDataset = data.previousData.datasets.find((prev, prevIndex) => {
                        if (prev.label === dataset.label) {
                            previousDatasetIndex = prevIndex;
                            return true;
                        }
                        return false;
                    });
                    if (previousDataset && previousDataset.data) {
                        previousData = previousDataset.data.reduce((a, b) => Number(a) + Number(b), 0);
                    }
                }
                const legendItem = document.createElement('div');
                legendItem.className = 'wps-postbox-chart--item';

                const previousDataHTML = previousData !== null ? `
                <div class="previous-data">
                    <span>
                        <span class="wps-postbox-chart--item--color" style="border-color: ${dataset.borderColor}"></span>
                        <span class="wps-postbox-chart--item--color" style="border-color: ${dataset.borderColor}"></span>
                    </span>
                    ${previousData.toLocaleString()}
                </div>` : '';

                legendItem.innerHTML = `
                <span>${dataset.label}</span>
                <div>
                    <div class="current-data">
                        <span class="wps-postbox-chart--item--color" style="border-color: ${dataset.borderColor}"></span>
                        ${currentData.toLocaleString()}
                    </div>
                    ${previousDataHTML}
                </div>`;

                const currentDataDiv = legendItem.querySelector('.current-data');
                currentDataDiv.addEventListener('click', function () {
                    const metaMain = lineChart.getDatasetMeta(index);
                    metaMain.hidden = !metaMain.hidden;
                    currentDataDiv.classList.toggle('wps-line-through');
                    lineChart.update();
                });

                const previousDataDiv = legendItem.querySelector('.previous-data');
                if (previousDataDiv && previousDatasetIndex !== null) {
                    previousDataDiv.addEventListener('click', function () {
                        const metaPrevious = lineChart.data.datasets.find((dataset, dsIndex) => {
                            return dataset.label === `${datasets[index].label} (Previous)` && lineChart.getDatasetMeta(dsIndex);
                        });
                        if (metaPrevious) {
                            const metaPreviousIndex = lineChart.data.datasets.indexOf(metaPrevious);
                            const metaPreviousVisibility = lineChart.getDatasetMeta(metaPreviousIndex);
                            metaPreviousVisibility.hidden = !metaPreviousVisibility.hidden;
                            previousDataDiv.classList.toggle('wps-line-through');

                            const allPreviousData = legendContainer.querySelectorAll('.previous-data');
                            const allHaveLineThrough = Array.from(allPreviousData).every(el => el.classList.contains('wps-line-through'));

                            if (previousPeriod) {
                                if (allHaveLineThrough) {
                                    previousPeriod.classList.add('wps-line-through');
                                } else {
                                    previousPeriod.classList.remove('wps-line-through');
                                }
                            }

                            lineChart.update();
                        }
                    });
                }
                legendContainer.appendChild(legendItem);
            }
        });
    }
}

const deepCopy = (obj) => JSON.parse(JSON.stringify(obj));

const chartInstances = {};

const getDisplayTextForUnitTime = (unitTime, tag_id) => {
    const select = document.querySelector(`#${tag_id}`).closest('.o-wrap').querySelector('.js-unitTimeSelect');
    if (select) {
        const option = select.querySelector(`.wps-unit-time-chart__option[data-value="${unitTime}"]`);
        if (option) {
            return option.textContent.trim();
        }
    }
    return unitTime;
}

wps_js.new_line_chart = function (data, tag_id, newOptions = null, type = 'line') {
    sortTotal(data.data.datasets);
    const realdata = deepCopy(data);
    const phpDateFormat = wps_js.isset(wps_js.global, 'options', 'wp_date_format') ? wps_js.global['options']['wp_date_format'] : 'MM/DD/YYYY';
    let momentDateFormat = phpToMomentFormat(phpDateFormat);
    const isInsideDashboardWidgets = document.getElementById(tag_id).closest('#dashboard-widgets') !== null;
    // Determine the initial unitTime
    const length = data.data.labels.map(dateObj => dateObj.formatted_date).length;

    const threshold = type === 'performance' ? 30 : 60;
    let unitTime = length <= threshold ? 'day' : length <= 180 ? 'week' : 'month';

    const datasets = [];

    // Check if there is only one data point
    const isSingleDataPoint = data.data.labels.length === 1;

    const select = document.querySelector(`#${tag_id}`).closest('.o-wrap').querySelector('.js-unitTimeSelect');
    if (select) {
        const selectedItem = select.querySelector('.wps-unit-time-chart__selected-item');
        if (selectedItem) {
            selectedItem.textContent = getDisplayTextForUnitTime(unitTime, tag_id);
        }
        const options = select.querySelectorAll('.wps-unit-time-chart__option');
        options.forEach(opt => {
            if (opt.getAttribute('data-value') === unitTime) {
                opt.classList.add('selected');
            } else {
                opt.classList.remove('selected');
            }
        });
    }

    const day = aggregateData(realdata.data.labels, realdata.data.datasets, 'day', momentDateFormat, isInsideDashboardWidgets);
    const week = aggregateData(realdata.data.labels, realdata.data.datasets, 'week', momentDateFormat, isInsideDashboardWidgets);
    const month = aggregateData(realdata.data.labels, realdata.data.datasets, 'month', momentDateFormat, isInsideDashboardWidgets);

    const prevDay = realdata?.previousData
        ? aggregateData(realdata.previousData.labels, realdata.previousData.datasets, 'day', momentDateFormat, isInsideDashboardWidgets)
        : null;
    const prevWeek = realdata.previousData
        ? aggregateData(realdata.previousData.labels, realdata.previousData.datasets, 'week', momentDateFormat, isInsideDashboardWidgets)
        : null;
    const prevMonth = realdata.previousData
        ? aggregateData(realdata.previousData.labels, realdata.previousData.datasets, 'month', momentDateFormat, isInsideDashboardWidgets)
        : null;

    // Initialize dateLabels based on the selected unitTime
    let dateLabels = unitTime === 'day'
        ? day.aggregatedLabels
        : unitTime === 'week'
            ? week.aggregatedLabels
            : month.aggregatedLabels;

// Initialize monthTooltip and prevMonthTooltip
    let monthTooltip = unitTime === 'day'
        ? day.monthTooltipTitle
        : unitTime === 'week'
            ? week.monthTooltipTitle
            : month.monthTooltipTitle;

    let prevMonthTooltip = unitTime === 'day'
        ? (prevDay ? prevDay.monthTooltipTitle : [])
        : unitTime === 'week'
            ? (prevWeek ? prevWeek.monthTooltipTitle : [])
            : (prevMonth ? prevMonth.monthTooltipTitle : []);
    let prevDateLabels = [];
    let prevAggregatedData = [];

    if (prevWeek) {
        prevDateLabels = prevWeek.aggregatedLabels;
        prevAggregatedData = prevWeek.aggregatedData;
        while (prevDateLabels.length < dateLabels.length) {
            prevDateLabels.push("N/A");
            prevAggregatedData.forEach(dataset => dataset.push(0));
        }
    } else {
        prevDateLabels = Array(dateLabels.length).fill("N/A");
        if (datasets && datasets.length > 0 && Array.isArray(datasets)) {
            prevAggregatedData = datasets.map(() => Array(dateLabels.length).fill(0));
        }
    }

    function updateChart(unitTime) {
        const displayText = getDisplayTextForUnitTime(unitTime, tag_id);
        const chartElement = document.getElementById(tag_id);
        const chartContainer = chartElement.parentElement.parentElement.querySelector('.wps-postbox-chart--data');
        const previousPeriodElement = chartContainer?.querySelector('.wps-postbox-chart--previousPeriod');
        if (previousPeriodElement) {
            previousPeriodElement.classList.remove('wps-line-through');
        }

        const select = document.querySelector(`#${tag_id}`).closest('.o-wrap').querySelector('.js-unitTimeSelect');
        if (select) {
            const selectedItem = select.querySelector('.wps-unit-time-chart__selected-item');
            if (selectedItem) {
                selectedItem.textContent = displayText;
            }
        }
        let aggregatedData, prevAggregatedData;
        switch (unitTime) {
            case 'day':
                aggregatedData = day;
                prevAggregatedData = prevDay;
                break;
            case 'week':
                aggregatedData = week;
                prevAggregatedData = prevWeek;
                break;
            case 'month':
                aggregatedData = month;
                prevAggregatedData = prevMonth;
                break;
            default:
                aggregatedData = day;
                prevAggregatedData = prevDay;
        }

        dateLabels = aggregatedData.aggregatedLabels;
        monthTooltip = aggregatedData.monthTooltipTitle;

        prevDateLabels = prevAggregatedData ? prevAggregatedData.aggregatedLabels : [];
        prevMonthTooltip = prevAggregatedData ? prevAggregatedData.monthTooltipTitle : [];

        // If prevDateLabels is empty, fill it with "N/A" for each month
        if (prevDateLabels.length === 0 && dateLabels.length > 0) {
            prevDateLabels = Array(dateLabels.length).fill("N/A");
        }

        const datasets = data.data.datasets.map((dataset, idx) => {
            const datasetType = dataset.type || (type === 'performance' && idx === 2 ? 'bar' : 'line');
            return {
                ...dataset,
                type: datasetType, // Set the type explicitly
                data: aggregatedData.aggregatedData[idx],
                borderColor: chartColors[data.data.datasets[idx].slug] || chartColors[`Other${idx}`],
                backgroundColor: chartColors[data.data.datasets[idx].slug] || chartColors[`Other${idx}`],
                fill: false,
                yAxisID: datasetType === 'bar' ? 'y1' : 'y', // Use y1 for bar, y for line
                borderWidth: datasetType === 'line' ? 2 : undefined,
                pointRadius: datasetType === 'line' ? dateLabels.length === 1 ? 5 : 0 : undefined,
                pointBorderColor: datasetType === 'line' ? 'transparent' : undefined,
                pointBackgroundColor: datasetType === 'line' ? chartColors[data.data.datasets[idx].slug] || chartColors[`Other${idx}`] : undefined,
                pointBorderWidth: datasetType === 'line' ? 2 : undefined,
                hoverPointRadius: datasetType === 'line' ? 6 : undefined,
                hoverPointBorderColor: datasetType === 'line' ? '#fff' : undefined,
                hoverPointBackgroundColor: chartColors[data.data.datasets[idx].slug] || chartColors[`Other${idx}`],
                hoverPointBorderWidth: datasetType === 'line' ? 4 : undefined,
                tension: datasetType === 'line' ? chartTensionValues[idx % chartTensionValues.length] : undefined,
                hitRadius: 10,
                meta: {
                    incompletePeriods: aggregatedData.isIncompletePeriod || []
                },
                segment: datasetType === 'line' ? {
                    borderDash: (ctx) => {
                        const incompletePeriods = ctx.chart.data.datasets[ctx.datasetIndex]?.meta?.incompletePeriods || [];
                        const currentIncomplete = incompletePeriods[ctx.p1DataIndex];
                        const previousIncomplete = incompletePeriods[ctx.p0DataIndex];
                        // Dash if either end of segment is in incomplete period
                        if (currentIncomplete || previousIncomplete) {
                            return [5, 5];
                        }
                        return undefined;
                    }
                } : undefined
            };
        });

        if (prevAggregatedData) {
            data.previousData.datasets.forEach((dataset, idx) => {
                datasets.push({
                    ...dataset,
                    type: 'line', // Previous datasets are always lines
                    label: `${dataset.label} (Previous)`,
                    data: prevAggregatedData.aggregatedData[idx],
                    borderColor: wps_js.hex_to_rgba(chartColors[dataset.slug] || chartColors[`Other${idx}`], 0.7),
                    hoverBorderColor: chartColors[data.data.datasets[idx].slug] || chartColors[`Other${idx}`],
                    backgroundColor: chartColors[data.data.datasets[idx].slug] || chartColors[`Other${idx}`],
                    fill: false,
                    yAxisID: 'y',
                    borderWidth: 1,
                    borderDash: [5, 5],
                    pointRadius: aggregatedData.aggregatedLabels.length === 1 ? 5 : 0,
                    pointBorderColor: 'transparent',
                    pointBackgroundColor: chartColors[data.data.datasets[idx].slug] || chartColors[`Other${idx}`],
                    pointBorderWidth: 2,
                    hoverPointRadius: 6,
                    hoverPointBorderColor: '#fff',
                    hoverPointBackgroundColor: chartColors[data.data.datasets[idx].slug] || chartColors[`Other${idx}`],
                    hoverPointBorderWidth: 4,
                    tension: chartTensionValues[idx % chartTensionValues.length],
                    hitRadius: 10
                });
            });
        }

        // Calculate max values for y and y1 axes
        const yAxisData = datasets
            .filter(dataset => dataset.yAxisID === 'y')
            .flatMap(dataset => dataset.data)
            .filter(val => typeof val === 'number' && !isNaN(val));
        const y1AxisData = datasets
            .filter(dataset => dataset.yAxisID === 'y1')
            .flatMap(dataset => dataset.data)
            .filter(val => typeof val === 'number' && !isNaN(val));

        const yMax = yAxisData.length > 0 ? Math.max(...yAxisData) : 0;
        const y1Max = y1AxisData.length > 0 ? Math.max(...y1AxisData) : 0;

        // Set dynamic stepSize based on max values
        const maxTicksY = isInsideDashboardWidgets ? 4 : 7;
        const stepSizeY = yMax > 0 ? Math.ceil(yMax / maxTicksY) : 1;
        const maxTicksY1 = 7;
        const stepSizeY1 = y1Max > 0 ? Math.ceil(y1Max / maxTicksY1) : 1;

        lineChart.options.scales.y.ticks.stepSize = Math.max(1, stepSizeY);
        if (lineChart.options.scales.y1) {
            lineChart.options.scales.y1.ticks.stepSize = Math.max(1, stepSizeY1);
        }

        lineChart.data.labels = dateLabels;
        lineChart.options.scales.x.offset = lineChart.data.labels.length === 1;
        lineChart.data.datasets = datasets;
        lineChart.options.scales.x.ticks.maxTicksLimit = isInsideDashboardWidgets
            ? unitTime === 'week' ? 2 : 4
            : unitTime === 'week' ? 3 : unitTime === 'month' ? 7 : 9;
        lineChart.options.plugins.tooltip.unitTime = unitTime;
        lineChart.options.plugins.tooltip.external = (context) =>
            externalTooltipHandler(context, realdata, dateLabels, prevDateLabels, monthTooltip, prevMonthTooltip);
        updateLegend(lineChart, datasets, tag_id, data);
        lineChart.update();
    }

    let ctx_line = document.getElementById(tag_id).getContext('2d');

    Object.keys(data.data.datasets).forEach((key, index) => {
        let color = chartColors[data.data.datasets[key].slug] || chartColors[`Other${index + 1}`];
        let tension = chartTensionValues[index % chartTensionValues.length];

        let datasetType = 'line'; // Default to line
        if (type === 'performance' && index === 2) {
            datasetType = 'bar'; // Set to bar for index 2 in performance charts
        }

        const dataset = {
            type: datasetType,
            label: data.data.datasets[key].label,
            data: data.data.datasets[key].data,
            backgroundColor: color,
            hoverBackgroundColor: color,
            hoverPointBackgroundColor: color,
            yAxisID: datasetType === 'bar' ? 'y1' : 'y', // Use y1 for bar, y for line
        };
        if (datasetType === 'line') {
            dataset.borderColor = color;
            dataset.fill = false;
            dataset.borderWidth = 2;
            dataset.pointRadius = 0;
            dataset.pointBorderColor = 'transparent';
            dataset.pointBackgroundColor = color;
            dataset.pointBorderWidth = 2;
            dataset.hoverPointRadius = 6;
            dataset.hoverPointBorderColor = '#fff';
            dataset.hoverPointBorderWidth = 4;
            dataset.tension = tension;
            dataset.hitRadius = 10;
        }
        datasets.push(dataset);
    });

    if (data?.previousData) {
        Object.keys(data.previousData.datasets).forEach((key, index) => {
            let color = chartColors[data.previousData.datasets[key].slug] || chartColors[`Other${index}`];
            let tension = chartTensionValues[index % chartTensionValues.length];

            datasets.push({
                type: 'line',
                label: `${data.previousData.datasets[key].label} (Previous)`,
                data: data.previousData.datasets[key].data,
                borderColor: wps_js.hex_to_rgba(color, 0.7),
                hoverBorderColor: color,
                backgroundColor: color,
                fill: false,
                yAxisID: 'y',
                borderWidth: 1,
                borderDash: [5, 5],
                pointRadius: 0,
                pointBorderColor: 'transparent',
                pointBackgroundColor: color,
                pointBorderWidth: 2,
                hoverPointRadius: 6,
                hoverPointBorderColor: '#fff',
                hoverPointBackgroundColor: color,
                hoverPointBorderWidth: 4,
                tension: tension,
                hitRadius: 10
            });
        });
    }

    const defaultOptions = {
        maintainAspectRatio: false,
        resizeDelay: 200,
        animation: {duration: 0},
        responsive: true,
        interaction: {intersect: false, mode: 'index'},
        plugins: {
            legend: false,
            tooltip: {
                enabled: false,
                external: (context) => externalTooltipHandler(context, realdata, dateLabels, prevDateLabels, monthTooltip, prevMonthTooltip),
                unitTime: unitTime, // Set initial unitTime
            },
        },
        scales: {
            x: {
                offset: isSingleDataPoint,
                grid: {display: false, drawBorder: false, tickLength: 0, drawTicks: false},
                border: {color: 'transparent', width: 0},
                ticks: {
                    align: 'inner',
                    autoSkip: true,
                    maxTicksLimit: isInsideDashboardWidgets ? (unitTime === 'week' ? 2 : 4) : (unitTime === 'week' ? 3 : unitTime === 'month' ? 7 : 9),
                    font: {
                        color: '#898A8E',
                        style: 'italic',
                        weight: 'lighter',
                        size: isInsideDashboardWidgets ? (unitTime === 'week' ? 9 : 11) : (unitTime === 'week' ? 11 : 13)
                    },
                    padding: 8,
                }
            },
            y: {
                min: 0,
                suggestedMax: 4,
                ticks: {
                    autoSkip: true,
                    maxTicksLimit: isInsideDashboardWidgets ? 4 : 7,
                    fontColor: '#898A8E',
                    fontSize: 13,
                    fontStyle: 'italic',
                    fontWeight: 'lighter',
                    padding: 8,
                    lineHeight: 15,
                    callback: renderFormatNum,
                },
                afterBuildTicks: wpsBuildTicks,
                border: {color: 'transparent', width: 0},
                type: 'linear',
                position: 'right',
                grid: {display: true, tickMarkLength: 0, drawBorder: false, tickColor: '#EEEFF1', color: '#EEEFF1'},
                gridLines: {drawTicks: false},
                title: {display: false},
            }
        },
    };

    if (type === 'performance' && data.data.datasets.length > 2) {
        defaultOptions.scales.y1 = {
            type: 'linear',
            position: 'left',
            border: {color: 'transparent', width: 0},
            grid: {display: false, drawBorder: false, tickLength: 0},
            ticks: {
                autoSkip: true,
                maxTicksLimit: 7,
                fontColor: '#898A8E',
                fontSize: 13,
                fontStyle: 'italic',
                fontFamily: '"Roboto",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
                fontWeight: 'lighter',
                padding: 8,
                lineHeight: 15,
                callback: renderFormatNum,
            },
            afterBuildTicks: wpsBuildTicks,
            title: {
                display: true,
                text: `${wps_js._('published')} Posts`,
                color: '#898A8E',
                fontSize: 13
            }
        };

        defaultOptions.scales.y = {
            border: {color: 'transparent', width: 0},
            ticks: {
                autoSkip: true,
                maxTicksLimit: 9,
                fontColor: '#898A8E',
                fontSize: 13,
                fontStyle: 'italic',
                fontFamily: '"Roboto",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
                fontWeight: 'lighter',
                padding: 8,
                lineHeight: 15,
                callback: renderFormatNum,
            },
            position: 'right',
            grid: {display: true, borderDash: [5, 5], tickColor: '#EEEFF1', color: '#EEEFF1'},
            title: {
                display: true,
                text: wps_js._('visits'),
                color: '#898A8E',
                fontSize: 13,
            }
        };
    }

    const lineChart = new Chart(ctx_line, {
        type: type === 'performance' && data.data.datasets.length > 2 ? 'bar' : 'line',
        data: {labels: [], datasets: []},
        plugins: [drawVerticalLinePlugin],
        options: Object.assign({}, defaultOptions, newOptions)
    });

    updateChart(unitTime);
    chartInstances[tag_id] = {chart: lineChart, updateChart: updateChart};

    return chartInstances[tag_id];
};

document.body.addEventListener('click', function (event) {
    const select = event.target.closest('.wps-unit-time-chart__selected-item');
    const option = event.target.closest('.wps-unit-time-chart__option');

    if (select) {
        if (!option) {
            document.querySelectorAll('.js-unitTimeSelect.open').forEach(openSelect => {
                if (openSelect !== select) {
                    openSelect.parentElement.classList.remove('open');
                }
            });
            select.parentElement.classList.toggle('open');
        }
        event.stopImmediatePropagation();
    } else if (option) {
        const select = option.closest('.js-unitTimeSelect');
        const selectedValue = option.getAttribute('data-value');

        if (select) {
            const selectedItem = select.querySelector('.wps-unit-time-chart__selected-item');
            if (selectedItem) {
                selectedItem.textContent = option.textContent.trim();
            }
            const options = select.querySelectorAll('.wps-unit-time-chart__option');
            options.forEach(opt => opt.classList.remove('selected'));
            option.classList.add('selected');

            select.classList.remove('open');
            const chartContainer = select.closest('.o-wrap').querySelector('.wps-postbox-chart--container');
            const canvas = chartContainer.querySelector('canvas');
            const canvas_id = canvas.getAttribute('id');
            if (chartInstances[canvas_id]) {
                chartInstances[canvas_id].updateChart(selectedValue);
            }
        }
        event.stopImmediatePropagation();
    } else {
        document.querySelectorAll('.js-unitTimeSelect.open').forEach(openSelect => {
            openSelect.classList.remove('open');
        });
    }
});

window.renderWPSLineChart = function (chartId, data ,newOptions) {
    const chartItem = document.getElementById(chartId);
    if (chartItem) {
        const parentElement = jQuery(`#${chartId}`).parent();
        const placeholder = wps_js.rectangle_placeholder();
        parentElement.append(placeholder);

        if (!data?.data?.datasets || data.data.datasets.length === 0) {
            parentElement.html(wps_js.no_results());
            jQuery('.wps-ph-item').remove();
        } else {
            wps_js.new_line_chart(data, chartId, newOptions);
            jQuery('.wps-ph-item').remove();
            jQuery('.wps-postbox-chart--data').removeClass('c-chart__wps-skeleton--legend');
            parentElement.removeClass('c-chart__wps-skeleton');
        }
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit