Jump to content

User:Ainali/PreViewStats.js

From Meta, a Wikimedia project coordination wiki

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// ==UserScript==
// @name         PreViewStats
// @description  Add quick page view stats with a sparkline to Wikimedia pages
// @author       Ainali
// @grant        none
// @translation  Feel free to contribute translations!
// @instruction  add to your global.js: importScript('meta:User:Ainali/PreViewStats.js');
// ==/UserScript==

(function() {
    'use strict';

    // Define translations
    const translations = {
        en: {
            views: 'views',
            fromYesterday: 'from yesterday',
            viewFullStats: 'View Full Stats'
        },
        de: {
            views: 'Aufrufe',
            fromYesterday: 'seit gestern',
            viewFullStats: 'Alle Statistiken anzeigen'
        },
        sv: {
            views: 'visningar',
            fromYesterday: 'från igår',
            viewFullStats: 'Visa all statistik'
        }
        // Add more languages here
    };

    // Get the user's interface language code
    const userLang = mw.config.get('wgUserLanguage');
    const strings = translations[userLang] || translations.en; // Fallback to English if no translation is found

    // Function to get page views data
    function getPageViews(title, project, callback) {
        const today = new Date();
        const endDate = today.toISOString().slice(0, 10).replace(/-/g, '');
        const startDate = new Date(today.setDate(today.getDate() - 30)).toISOString().slice(0, 10).replace(/-/g, '');
        const apiUrl = `https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/${project}/all-access/all-agents/${title}/daily/${startDate}/${endDate}`;

        fetch(apiUrl)
            .then(response => response.json())
            .then(data => {
                if (data.items) {
                    callback(data.items);
                } else {
                    console.log('No data found.');
                }
            })
            .catch(error => console.error('Error fetching page views:', error));
    }

    // Function to create a sparkline using Canvas
    function createSparkline(views) {
        const canvas = document.createElement('canvas');
        canvas.width = 80;  // Sparkline width
        canvas.height = 30; // Sparkline height
        const ctx = canvas.getContext('2d');

        const viewValues = views.map(day => day.views);

        const maxValue = Math.max(...viewValues);

        const xStep = canvas.width / (viewValues.length - 1);
        const yScale = (canvas.height - 2) / maxValue;

        ctx.beginPath();
        ctx.moveTo(0, canvas.height - viewValues[0] * yScale);

        viewValues.forEach((value, index) => {
            ctx.lineTo(index * xStep, canvas.height - value * yScale);
        });

        ctx.strokeStyle = '#007bff'; // Line color
        ctx.lineWidth = 1.5;         // Line width
        ctx.stroke();

        return canvas;
    }

    // Function to display page views and append sparkline
    function displayPageViews(views, project) {
        const lastDay = views[views.length - 1].views;
        const previousDay = views[views.length - 2].views;
        const streak = lastDay > previousDay ? "↑" : "↓";

        const viewData = `${lastDay} ${strings.views} (${streak}${Math.abs(lastDay - previousDay)} ${strings.fromYesterday})`;

        // Create a container for the clickable link
        const viewContainer = document.createElement('a');
        viewContainer.href = `https://pageviews.wmcloud.org/?project=${project}&platform=all-access&agent=user&redirects=0&range=latest-30&pages=${encodeURIComponent(mw.config.get('wgPageName'))}`;
        viewContainer.target = '_blank'; // Open link in a new tab
        viewContainer.style = `
             display: inline-flex; 
             align-items: center; 
             padding: 2px 5px; 
             font-size: 12px; 
             margin-left: 10px; 
             text-decoration: none; 
             color: inherit;
             `       ;
        // Set the tooltip
        viewContainer.title = strings.viewFullStats;

        const textSpan = document.createElement('span');
        textSpan.textContent = viewData;
        textSpan.style = `padding-right: 5px;`
        viewContainer.appendChild(textSpan);

        const sparkline = createSparkline(views);
        viewContainer.appendChild(sparkline);

        // Insert the viewContainer after the "Talk" tab
        const talkTab = document.getElementById('ca-talk');
        if (talkTab && talkTab.parentNode) {
            talkTab.parentNode.insertBefore(viewContainer, talkTab.nextSibling);
        }
    }

    // Fetch and display page views and sparkline for the current page
    const title = mw.config.get('wgPageName');
    const project = mw.config.get('wgServerName'); // Get the server name, e.g., 'en.wikipedia.org'

    getPageViews(title, project, (views) => displayPageViews(views, project));

})();