MediaWiki:ArticleRating/Insights.js

/** * @name       ArticleRating Insights * @version    1.0 * @description Creates an Insights special page for ArticleRating * @author     KhangND */ require(['wikia.window', 'mw', 'jquery', 'ext.wikia.design-system.loading-spinner'], function(window, mw, $, Spinner) {   'use strict';

var $content = $('#mw-content-text'); var $spinner = $(       new Spinner.html            .replace('wds-block', 'wds-spinner__block')            .replace('wds-path', 'wds-spinner__stroke')            .replace('stroke-width=""', 'stroke-width="3"')    ); var ARInsights = { /**        * @properties: * {number} imports * {string} storage * {constructor} api * {object} i18n * {object} colors * {object} icons * {method} icon * {array}  articles */   };    ARInsights.imports = 3, ARInsights.storage = 'Module:Rating-storage', ARInsights.icons = { most: 'poll', highest: 'upvote', lowest: 'upvote' },   ARInsights.api = new mw.Api, /**    * @method      prepare * @desc       Prepares imported scripts * @returns    {void} */   ARInsights.prepare = function { if(--this.imports > 0) return; this.icon  = window.dev.wds.icon; this.colors = window.dev.colors; window.dev.i18n .loadMessages('ArticleRating') .done($.proxy(this.preload, this)); },   /**     * @method      preload * @desc       Preloads data and i18n * @returns    {void} */   ARInsights.preload = function(i18nLoaded) { this.api.get({           action: 'parse',            text: '',            prop: 'text',            disablepp: true        }).done($.proxy(function(data) { data = $(data.parse.text['*']); if(data.find('a').length) return; data = data.text; try { data = JSON.parse(data.substr(2, data.length)); } catch(e) { return; }

// stores articles in an array for sorting purpose this.articles = []; var i = 0, ids  = Object.keys(data), rates = Object.values(data), sum = function(sum, num) { return sum + num }; for(i in ids) { var total = Object.keys(rates[i]).length; this.articles[i] = { id: ids[i], info: rates[i], rates: total, avg: Object.values(rates[i]).reduce(sum) / total };           }            this.i18n = i18nLoaded._messages.en; for(i in this.i18n) { this.i18n[i] = i18nLoaded.msg(i).escape; }           this.init; }, this)); },   /**     * @method      init * @desc       Initializes components and data * @returns    {void} */   ARInsights.init = function { // add internal css var bgColor = this.colors.parse(this.colors.wikia.page), bdColor = this.colors.parse(this.colors.wikia.menu), pageBright = bgColor.isBright, style = '.rating-col {' + 'background: $bg;' + 'border-top: 4px solid $bd' + '}' +           '.rating-bars { background-color: $bg }' + '.rating-bars > div { background-color: $bd }' + '.rating-table th,' + '.rating-details .head {' + 'background-color: $bg;' + 'border-top: 3px solid $bd' + '}';       mw.util.addCSS(            this.colors.css(style, { bg: pageBright ? bgColor.lighten(-5) : bgColor.lighten(5), bd: bdColor })       );

// modify blank page var title = $('title').text; $('title').text(title.replace(title.split('|')[0], this.i18n.insights + ' ')); $('.page-header__title').text('ArticleRating: ' + this.i18n.insights); $content.html($spinner).after(           $(' ', { id: 'rating-footer', append: [ $(' ', { text: this.i18n.poweredby + ' ArticleRating'}), $('', {                       href: '//dev.fandom.com/wiki/ArticleRating',                        text: this.i18n.doc                    }), ' | ',                   $('', {                        href: '//dev.fandom.com/wiki/Talk:ArticleRating',                        text: this.i18n.report                    }) ]           })        );

// get 50 page titles each due to API limit var total = this.articles.length, iter = 50, limit = total < iter ? total : iter, loops = Math.ceil(total / limit), titles = []; for(var i = 0; i < loops; i++) { var ids = []; for(var j = i * iter; j < limit; j++) ids.push(this.articles[j].id); this.getTitles(ids, titles, limit === total); if (limit > total - limit) limit = total; }   },    /**     * @method      getTitles * @desc       Retrieves page titles with API * @param      {Array} ids: page ids to retrieve from * @param      {Array} titles: cache * @param      {Boolean} isDone: flags continue if done * @returns    {void} */   ARInsights.getTitles = function(ids, titles, isDone) { this.api.get({           action: 'query',            pageids: ids.join('|')        }).done(            $.proxy(function(data) { var pages = Object.values(data.query.pages), i = 0; for(i in pages) { titles.push(pages[i].title); }               if(isDone) { // purge page if API query is bugged if(titles.length < this.articles.length) { this.api.get({                           action: 'purge',                            titles: mw.config.get('wgPageName')                        }).done(function {                            location.reload(true);                        }); return; }                   for(i in titles) { if(titles[i]) { this.articles[i].title = titles[i]; } else { titles.splice(i, 1); this.articles.splice(i, 1); }                   }                    this.create; }           }, this)        ); },   /**     * @method      getArticle * @desc       Returns an article from the specified type * @param      {string} t: article type * @returns    {object} */   ARInsights.getArticle = function(t) { var byRate = function(a, b) { return a.rates - b.rates }, byAvg = function(a, b) { return a.avg - b.avg || a.rates - b.rates }, clone = this.articles.slice(0); switch(t) { case 'most': // most rated return clone.sort(byRate)[clone.length - 1]; case 'highest': // highest rated return clone.sort(byAvg)[clone.length - 1]; case 'lowest': // lowest rated return clone.sort(byAvg)[0]; }   },    /**     * @method      create * @desc       Creates elements * @returns    {void} */   ARInsights.create = function { $content .empty .append(this.board('most', this.getArticle('most'))) .append(this.board('highest', this.getArticle('highest'))) .append(this.board('lowest', this.getArticle('lowest'))) .append([           $(' ')            .addClass('rating-table')            .append( $(' ').append([                   $(' ', { text: 'Article' + ' ' }),                    $(' ', { text: this.i18n.avgrating + ' ' }),                    $(' ', { text: this.i18n.totalrating + ' ' }),                    $(' ').addClass('unsortable'),                ]), this.rows )           .tablesorter,            $(' ')            .addClass('rating-details')            .append([ $(' ', { 'class': 'head', text: 'Details' }), $(' ')           ])        ]);    },    /**     * @method      board * @desc       Creates a featured board * @param      {string} t: board type * @param      {object} d: data * @returns    {jQuery} */   ARInsights.board = function(t, d) { return $(' ', {           'class': 'rating-col',            append: [                $(' ', { 'class': 'rating-icon', html: this.icon(this.icons[t]) }),               $(' ', {                    'class': 'rating-title', text: 'Rated'//this.i18n[t] }),               $('', { 'class': 'rating-link', href: mw.util.getUrl(d.title), text: d.title }),               $(' ', {                    'class': 'rating-foot', text: t === 'most' ? this.i18n.totalrating + ': ' + d.rates : this.i18n.avgrating + ': ' + d.avg.toFixed(1) })           ]        });    },    /**     * @method      rows * @desc       Creates table rows * @returns    {Array} */   ARInsights.rows = function { var res = []; for(var i in this.articles) { var article = this.articles[i]; res.push(               $(' ').append([ $(' ').append(                       $('', { href: mw.util.getUrl(article.title), text: article.title })                   ),                    $(' ').append(                        $(' ', { text: article.avg.toFixed(2) }),                        $(' ')                        .addClass('rating-bars')                        .progressbar({ value: article.avg, max: 5 })                   ),                    $(' ')                        .addClass('centered-text') .text(article.rates), $(' ')                       .addClass('centered-text') .append(                           $('', { href: '', html: this.icon('external-small'), 'data-details': article.id, click: this.detail })                       )                ])            );        }        return res; },   /**     * @method      detail * @desc       Displays rating details * @returns    {void} */   ARInsights.detail = function { var win = $(window), panelTop = $('.rating-details').offset.top; if (win.scrollTop > panelTop) win.scrollTop(panelTop - $('#globalNavigation').height); console.log($(this).data('details')); return false; };

importArticles({       type: 'style',        articles: 'u:dev:MediaWiki:ArticleRating.css'    }, {        type: 'script',        articles: [            'u:dev:MediaWiki:I18n-js/code.js',            'u:dev:MediaWiki:Colors/code.js',            'u:dev:MediaWiki:WDSIcons/code.js'        ]    }); mw.loader.using([       'mediawiki.api',        'mediawiki.util',        'jquery.ui.progressbar',        'jquery.tablesorter'    ]).then(function {        mw.hook('dev.i18n')  .add($.proxy(ARInsights.prepare, ARInsights));        mw.hook('dev.wds')   .add($.proxy(ARInsights.prepare, ARInsights));        mw.hook('dev.colors').add($.proxy(ARInsights.prepare, ARInsights));    }); });