User:YuviPanda/AssessmentBar.js

Source: Wikipedia, the free encyclopedia.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//<nowiki>
(function() {

    var MONTH_NAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    // Only on mainspace articles and mainspace talk pages
    if(mw.config.get('wgNamespaceNumber') > 1) {
        return;
    }
    var requires = [
        'jquery.ui',
        'jquery.ui',
        'jquery.ui',
        'mediawiki.api',
        '//en.wikipedia.org/w/index.php?title=User:YuviPanda/js-utils/underscore.js&action=raw&ctype=text/javascript',
        '//en.wikipedia.org/w/index.php?title=User:YuviPanda/js-utils/ClientTemplate.js&action=raw&ctype=text/javascript'
    ];

    var cssPath = '//en.wikipedia.org/w/index.php?title=User:YuviPanda/AssessmentBar.css&action=raw&ctype=text/css';

    // Loaded in externally
    var projectData = window.assBar.projectData; 

    function getArticleTitle(title) {
        // If in a talk page, returns original page title
        // Else returns title unmodified
        return title.replace(/^Talk:/i, "");
    }

    function loadScripts(scripts) {
        var deferreds = [];
        $.each(scripts, function(i, script) {
            if(script.match(/^(http:|https:|\/\/)/)) {
                // External script, use $.getScript
                deferreds.push($.getScript(script));
            } else {
                // Use mw.using, convert callbacks to deferreds
                var d = $.Deferred();
                mw.loader.using(script, function() {
                    d.resolve();
                }, function(err) {
                    d.reject(err);
                });
                deferreds.push(d);
            }
        });
        return $.when.apply($, deferreds);
    }

    var extractorRegex =  new RegExp("{{(?:" + projectData.inputTemplates.join('|') + ")\\s*(?:\\s*\\|\\s*.*=?.*\\s*)*\\s*}}");

    var ass = null; // Current assessment

    var api = null; // API wrapper

    var templates = null; // ClientTemplate instance

    function Assessment(project, data, rawText, title) {
        this.project = project;
        this.data = data;
        this.rawText = rawText;
        this.title = title
    }

    Assessment.prototype.toTemplate = function() {
        var template;
        var curDate = new Date();
        var dateString = MONTH_NAMES[curDate.getMonth()] + " " + curDate.getUTCFullYear();
        this.data['assess-date'] = dateString;
        template = "{{" + projectData.outputTemplate;
        $.each(this.data, function(key, value) {
            template += "|" + key + "=" + value;
        });
        template += "}}";
        return template;
    }

    Assessment.prototype.getDisplayData = function() {
        // Defaults in case they don't exist
        var displayData = {
            importance: "unassessed",
            'class': "unassessed"
        };
        $.each(this.data, function(key, value) {
            if(key === 'importance' || key === 'class') {
                if(!$.trim(value)) {
                    value = 'unassessed';
                }
            }
            if(value === 'yes' || value === 'y') {
                value = 'unassessed';
            }
            displayData[key] = value;
        });
        return displayData;
    }

    Assessment.prototype.getSubProjects = function() {
        var subProjects = {};
        $.each(this.data, function(key, value) {
            if(value.match(/y(es)?/i)) {
                value = "unassessed";
            }
            if($.inArray(key.replace(/-importance$/, ''), projectData.subProjects) != -1 && value != "" && !subProjects[key]) {
                subProjects[key.replace(/-importance$/, '')] = value;
            }
        });
        return subProjects;
    }

    Assessment.prototype.getActionItems = function() {
        var actionItems = {};
        var that = this;
        $.each(projectData.actionNeeded, function(i, action) {
            actionItems[action] = (that.data[action] === "yes");
        });
        return actionItems;
    }

    Assessment.prototype.removeSubProject = function(subProject) {
        delete this.data[subProject];
        delete this.data[subProject + "-importance"];
    }
    Assessment.prototype.addSubProject = function(subProject, importance) {
        this.data[subProject] = "yes";
        this.data[subProject + "-importance"] = importance;
    }
    Assessment.prototype.save = function() {
        var d = $.Deferred();
        // Kill 'auto' fields
        delete this.data['auto'];

        var text = this.rawText.replace(extractorRegex, this.toTemplate());

        api.post({
            action: 'edit',
            title: 'Talk:' + this.title,
            summary: 'Changed assessment status for ' + projectData.name + ' (via [[User:YuviPanda/AssessmentBar|AssessmentBar]])',
            text: text,
            token: mw.user.tokens.get('csrfToken')
        }, {
            ok: function(data) {
                d.resolve(data);
                console.log('Success!');
            }
        });
        return d;
    }

    Assessment.fromWikiText = function(text, title) {
        var match = text.match(extractorRegex);
        if(match === null) {
            return null;
        }
        var cleanTemplate = match[0].replace(/{|}|\n/g, '');
        var parts = cleanTemplate.split('|');
        var tags = {};
        for(var i = 1; i < parts.length; i++) {
            console.log(parts[i]);
            var tag = parts[i].split('=');
            tags[$.trim(tag[0])] = $.trim(tag[1]).toLowerCase();
        }
        return new Assessment(parts[0], tags, text, title);
    }

    function bindAssBarEvents() {
        $("#assbar-save").click(function() {
            var that = this;
            $(that).text("Saving...");
            ass.save().done(function() {
                $(that).text("Save");
                if(mw.config.get('wgPageName').match(/^Talk/)) {
                    location.reload(true); // Hard refresh
                }
            });
            return false;
        });

        $(".assbar-action-item").change(function() {
            var action = $(this).parents(".assbar-item").attr('data-action');
            if($(this).is(':checked')) {
                ass.data[action] = 'yes';
            } else {
                delete ass.data[action];
            }
        });

        $(".assbar-importance, .assbar-class").change(function() {
            var project = $(this).parents(".assbar-item").attr('data-project');
            var value = $(this).val().replace("unassessed", "");
            if(project == projectData.name) {
                // Main Project 
                var what = $(this).hasClass("assbar-importance") ? "importance" : "class";
                ass.data[what] = value; 
            } else {
                // One of the sub projects
                ass.data[project] = "yes";
                ass.data[project + "-importance"] = value;
            }
        });

        $("#assbar-new-subproject-name").autocomplete({
            source: projectData.subProjects,
            autoFocus: true
        });

        $("#assbar-add-new-subproject").click(function() {
            $("#assbar-new-subproject-dialog").dialog({
                modal: true,
                title: "Add new Sub Project",
                buttons: {
                    "Add": function() {
                        var subProject = $("#assbar-new-subproject-name").val();
                        var importance = $("#assbar-new-subproject-importance").val();
                        if($.inArray(subProject, projectData.subProjects) === -1) {
                            alert("Invalid subproject chosen!");
                            return;
                        }
                        ass.addSubProject(subProject, importance.replace("unassessed", ""));

                        var dialog = this;
                        templates.getTemplate('NewSubProject').done(function(template) {
                            var displayData = {
                                project: projectData,
                                subProject: subProject,
                                importance: importance
                            };
                            $(template(displayData)).appendTo("#assbar-subprojects-list");
                            $(dialog).dialog("close");
                        });
                    }
                }
            });
            return false;
        });

        $(".assbar-subproject-delete").click(function() {
            var subProject = $(this).parents(".assbar-item").attr('data-project');
            var sure = confirm("Do you want to delete the sub project " + subProject + "?");
            if(sure) {
                ass.removeSubProject(subProject);
                $(this).parents(".assbar-item").fadeOut();
            }
            return false;
        });

    }

    mw.loader.load(cssPath, 'text/css');
    loadScripts(requires).done(function() {
            api = new mw.Api();
            templates = new ClientTemplate('User:YuviPanda/AssessmentBar');
            $(function() {

                var title = getArticleTitle(mw.config.get('wgPageName'));
                api.get({
                    action: "parse",
                    page: 'Talk:' +  title,
                    prop: 'wikitext'
                }, {
                    ok: function(data) {
                        ass = Assessment.fromWikiText(data.parse.wikitext['*'], title);
                        if(!ass) {
                            return;
                        }
                        a = ass;
                        templates.getTemplate('Toolbar').done(function(template) {
                            var displayAss = {
                                project: projectData,
                                subProjects: ass.getSubProjects(),
                                actionItems: ass.getActionItems(),
                                data: ass.getDisplayData()
                            };
                            $(template(displayAss)).appendTo("body");
                            bindAssBarEvents();
                        });
                    }
                });

            });
    });
})();
//</nowiki>