User:Ladsgroup/dashboard.js

// License: GPL-v3 or later // Keep in sync with https://gitlab.wikimedia.org/ladsgroup/dashboard-gadget/-/blob/main/main.js

function dashboardGadget { function msg( key ){ const i18n = { 'en': { 'dashboard': 'Dashboard', 'dashboard-message': 'Go to the dashboard', 'loading': 'Loading...', 'diff': 'Diff', 'refresh': 'Refresh', 'configuration': 'Configuration', 'pending-since': 'Pending since', 'default-config': 'User:Ladsgroup/defaultDashboardConfig.json' },           'fa': { 'dashboard': 'پیشخوان', 'dashboard-message': 'رفتن به صفحهٔ پیشخوان عمومی', 'loading': 'در حال بارگذاری...', 'diff': 'تفاوت', 'refresh': 'بروزرسانی', 'configuration': 'تنظیمات', 'pending-since': 'در حال انتظار از', 'default-config': 'مدیاویکی:Gadget-dashboard/defaultConfig.json' },           'de': { 'dashboard': 'Dashboard', 'dashboard-message': 'Go to the dashboard', 'loading': 'Laden...', 'diff': 'Unterschied', 'refresh': 'Neuladen', 'configuration': 'Einstellungen', 'pending-since': 'Ungesichtet seit', 'default-config': 'User:Ladsgroup/defaultConfig.json' }       };        return i18n[ mw.config.get( 'wgUserLanguage' ).split('-')[0] ][ key ] || i18n.en[ key ]; }

// inject the link if ($('.vector-user-links').length) { // new vector let dashboardLinkDiv = $(' '); dashboardLinkDiv.css('margin', '5px'); let link = $(''); link.attr('href', '/wiki/Special:BlankPage/Dashboard'); link.text(msg('dashboard')) dashboardLinkDiv.append(link); dashboardLinkDiv.append(' - '); $('.vector-user-links').prepend(dashboardLinkDiv); } else { // old vector mw.util.addPortletLink('p-personal', '/wiki/Special:BlankPage/Dashboard', msg('dashboard'), 'p-dashboard', msg('dashboard-message'), null, '#pt-userpage'); }

if (       mw.config.get( 'wgCanonicalNamespace' ) != 'Special' ||        mw.config.get( 'wgCanonicalSpecialPageName' ) != 'Blankpage' ||        mw.config.get( 'wgPageName' ).search( '/Dashboard' ) == -1    ) { return; }   document.documentElement.classList.remove('vector-feature-limited-width-clientpref-1'); document.documentElement.classList.add('vector-feature-limited-width-clientpref-0'); document.documentElement.classList.remove('vector-feature-page-tools-pinned-enabled'); document.documentElement.classList.add('vector-feature-page-tools-pinned-disabled'); $('.vector-page-toolbar').remove; window.dispatchEvent( new Event( 'resize' ) ); $('.mw-first-heading').text(msg('dashboard')); document.title = msg('dashboard'); $('.mw-body-content').text(msg('loading'));

async function loadConfig( title ) { let response = await fetch("/wiki/" + encodeURIComponent(title) + '?action=raw'); return response.text; }

async function contentForPageType( box ) { let response = await fetch("/api/rest_v1/page/html/" + encodeURIComponent(box.pageTitle)); return response.text; }

async function contentForRC( box ) { let response = await fetch(box.url); let data = await response.json; data = data.query.recentchanges; let content = $(''); for ( i in data ) { let diff = $(''); diff.attr('href', '/wiki/Special:Diff/' + Number(data[i].revid)); diff.text(msg('diff'));

let liObj = $(''); liObj.append('(');           liObj.append(diff);            liObj.append(') - '); liObj.append(getPageLink(data[i].title)); liObj.append(' '); liObj.append(getUser(data[i].user)); liObj.append( ' (' + data[i].parsedcomment + ')' );

content.append(liObj); }       return content; }

async function contentForWatchlist( box ) { let response = await fetch(box.url); let data = await response.json; data = data.query.watchlist; let content = $(''); for ( i in data ) { let diff = $(''); diff.attr('href', '/wiki/Special:Diff/' + Number(data[i].revid)); diff.text(msg('diff'));

let liObj = $(''); liObj.append('(');           liObj.append(diff);            liObj.append(') - '); liObj.append(getPageLink(data[i].title)); liObj.append(' '); liObj.append(getUser(data[i].user)); liObj.append( ' (' + data[i].parsedcomment + ')' );

content.append(liObj); }

return content; }

async function contentForPending( box ) { let response = await fetch(box.url); let data = await response.json; data = data.query.oldreviewedpages; if ( !data ) { return 'Nothing to review!'; }       let content = $(''); for ( i in data ) { let diff = $('<a></a>'); diff.attr('href', '/wiki/Special:Diff/' + Number(data[i].revid)); diff.text(msg('diff'));

let liObj = $('<li></li>'); liObj.append('(');           liObj.append(diff);            liObj.append(') - '); liObj.append(getPageLink(data[i].title)); liObj.append( ' (' + msg('pending-since') + ': ' + data[i].pending_since + ')' );

content.append(liObj); }

return content; }

async function contentForCategory( box ) { let api = new mw.Api; if (box.norandom) { limit = 10; } else { limit = 100; }       let data = await api.get( {            action: 'query',            list: 'categorymembers',            cmprop: 'title',            cmlimit: limit,            cmtitle: box.categoryTitle        } ); data = getMultipleRandom(data.query.categorymembers, 10); let content = $('<ul></ul>'); for ( i in data ) { let liObj = $('<li></li>'); liObj.append(getPageLink(data[i].title)); content.append(liObj); }       return content; }

async function contentForLinks( box ) { let content = $('<ul></ul>'); for ( i in box.links ) { let link = box.links[i]; if ( link.page ) { let liObj = $('<li></li>'); liObj.append(getPageLink(link.page)); content.append(liObj); } else if ( link.url ) { let link = $('<a>'); link.attr('href', encodeURIComponent(link.url)); link.text(link.text); let liObj = $('<li></li>'); liObj.append(link); content.append(liObj); }       }

return content; }

async function contnetForStats { let api = new mw.Api; let data = await api.get( {           action: 'query',            meta: 'siteinfo',            siprop: 'statistics',        } ); let content = '<ul>'; content += '<li>تعداد مقالات: ' + mw.language.convertNumber(data.query.statistics.articles) + '</li>'; content += '<li>تعداد صفحات: ' + mw.language.convertNumber(data.query.statistics.pages) + '</li>'; content += '<li>تعداد ویرایش‌ها: ' + mw.language.convertNumber(data.query.statistics.edits) + '</li>'; content += '<li>تعداد تصاویر: ' + mw.language.convertNumber(data.query.statistics.images) + '</li>'; content += '<li>تعداد کاربران فعال: ' + mw.language.convertNumber(data.query.statistics.activeusers) + '</li>'; return content + '</ul>'; }

async function contnetForCx { let api = new mw.Api; let data = await api.get( {           action: 'query',            assert: 'user',            list: 'contenttranslationsuggestions',            from: 'en',            to: 'fa',            limit: 10,            seed: Math.floor(Math.random * 100)        } ); data = data.query.contenttranslationsuggestions.lists; let content = $('<ul></ul>'); for ( i in data ) { for (j in data[i].suggestions) { let link = $('<a>'); link.attr('href', 'https://en.wikipedia.org/wiki/' + encodeURIComponent(data[i].suggestions[j].title)); link.text(data[i].suggestions[j].title);

let liObj = $('<li></li>'); liObj.append(link); content.append(liObj); }       }        let divObj = $(' '); divObj.append(content); return divObj; }

const handlers = { 'page': contentForPageType, 'rc': contentForRC, 'watchlist': contentForWatchlist, 'category': contentForCategory, 'pending': contentForPending, 'links': contentForLinks, 'stats': contnetForStats, 'cx': contnetForCx, };

function getUser(username) { let link = $('<a>'); link.attr('href', '/wiki/User:' + encodeURIComponent(username)); link.text(username); return link; }

function getPageLink( title ) { let link = $('<a>'); link.attr('href', '/wiki/' + encodeURIComponent(title)); link.text(title); return link; }

function getMultipleRandom(arr, num) { const shuffled = [...arr].sort( => 0.5 - Math.random); return shuffled.slice(0, num); }

function loadBoxes { $('.mw-body-content').text(msg('loading')); let tabs = $(' '); let tabsHeader = $('<div class="cdx-tabs__header"><div class="cdx-tabs__list"> '); let tabsContent = $( '<div class="cdx-tabs__content"> '); for ( let tabIndex in window.dashboardConfig.tabs ) { let tabConfig = window.dashboardConfig.tabs[tabIndex]; let headerElement = $('<span class="cdx-tabs__list__item"> '); headerElement.text( tabConfig.title ); headerElement.on( 'click', => {                 window.dashboardActiveTab = tabIndex;                loadBoxes;            }); if ( tabIndex == ( window.dashboardActiveTab || 0 ) ) { headerElement.attr('aria-selected', true); }           tabsHeader.append(headerElement); let tabContent = $( ' '); tabContent.attr( 'id', 'tab-content-' + tabIndex ); tabContent.css('display', 'flex'); tabContent.css('flex-wrap', 'wrap'); tabContent.css('align-items', 'flex-start'); for (let i in tabConfig.boxes) { i = Number(i); let box = tabConfig.boxes[i]; let element = $('<span class="cdx-card__text"> '); let titleElement = $('<span class="cdx-card__text__title"> '); titleElement.text(box.title); element.append(titleElement); let contentElement = $(' '); contentElement.attr('class', 'cdx-card__text__supporting-text'); contentElement.attr('id', 'dashboard-box-' + i); contentElement.append(' '); contentElement.append(msg('loading')); contentElement.css('width', box.width || '300px' ); contentElement.css('height', box.height || '300px' ); contentElement.css('overflow', 'scroll' ); element.append(contentElement); let wrapper = $( ' ' ); wrapper.append(element); wrapper.css('padding', '15px' ); wrapper.css('margin', '15px' ); const activeTab = window.dashboardActiveTab || 0; if ( tabIndex == activeTab ) { wrapper.css('display', 'inline-flex'); tabsContent.append(wrapper); if ( handlers[box.type] ) { handlerPromise = handlers[box.type](box); } else { handlerPromise = new Promise( => { return 'No handler has been found' } ); }                   handlerPromise.then( ( content ) => { $( '#dashboard-box-' + i).html( content )}); } else { wrapper.css('display', 'none'); }           }        }        tabs.append(tabsHeader); let direction = 'left'; if (document.dir == 'rtl') { direction = 'right'; }

let refreshButton = $('<button class="cdx-button cdx-button--action-progressive"> '); refreshButton.append('<span class="cdx-button__icon cdx-css-icon--reload"> '); refreshButton.text(msg('refresh')); refreshButton.css( 'align-self', 'flex-end' ); refreshButton.css( 'margin-bottom', '5px' ); refreshButton.css( 'margin-' + direction, '5px' ); refreshButton.on('click', loadBoxes ); let configButton = $('<button class="cdx-button cdx-button--action-progressive"> '); configButton.append('<span class="cdx-button__icon cdx-css-icon--reload"> '); configButton.text(msg('configuration'));

let configLink = $('<a></a>'); configLink.attr('href', '/wiki/ ' + encodeURIComponent( window.dashboardConfigLocation )); configLink.attr('target', '_blank'); configLink.append(configButton); configLink.css( 'margin-bottom', '5px' ); configLink.css( 'margin-' + direction, 'auto'); tabsHeader.append( configLink ); tabsHeader.append( refreshButton ); tabs.append(tabsContent); $('.mw-body-content').html(tabs); }   let configPromise = null; if ( mw.util.getParamValue( 'dashboardConfig' ) ) { configPromise = loadConfig( mw.util.getParamValue( 'dashboardConfig' ) ); window.dashboardConfigLocation = mw.util.getParamValue( 'dashboardConfig' ); } else { configPromise = loadConfig('User:' + mw.config.get('wgUserName') + '/dashboardConfig.json' ) .then( function (res) {               try {                    JSON.parse(res);                    window.dashboardConfigLocation = 'User:' + mw.config.get('wgUserName') + '/dashboardConfig.json';                    return res;                } catch (erorr) {                    window.dashboardConfigLocation = msg('default-config');                    return loadConfig(msg('default-config'));                }            } ); }   configPromise.then( function (res) {        let config = JSON.parse(res);        window.dashboardConfig = config;        mw.loader.using('codex-styles').then( loadBoxes );    }); };

(function ($, mw) {   dashboardGadget; }(jQuery, mediaWiki));