User:Ponor/inline-patrol.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)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/*
Inline patrol in RECENT CHANGES, PAGE HISTORY and USER CONTRIBUTIONS
Adds [patrol] buttons for unpatrolled edits in RC/PH/UC. Calls MediaWiki API to patrol by Revision ID.
Author:Ponor, 2022-08-15. Inspired by Ivi1o4's PH/UC gadget.

Use with inline diff expansion scripts like [[:en:User:Bradv/Scripts/ExpandDiffs]] or [[:en:User:Writ_Keeper/Scripts/inlineDiffDocs]]
*/
$(document).ready(function() {
   //"use strict";

   if (window.inline_patrol_running ||
      !(mw.config.get("wgUserGroups").includes("patroller") || mw.config.get("wgUserGroups").includes("sysop")) ||
      !(mw.config.get("wgCanonicalSpecialPageName") === "Recentchanges" ||
         mw.config.get("wgCanonicalSpecialPageName") === "Contributions" ||
         mw.config.get("wgAction") === "history"
      )
   ) {
      return;
   } //get out of here

   //the script should not be loaded twice
   window.inline_patrol_running = true;

   //message translations
   const msg_patrol = window.ip_msg_patrol || "patrol"; //button; hr:"ophodi"
   const msg_patrol_hint = window.ip_msg_patrol_hint || "mark as patrolled: revision #"; //button hint; hr:"označi ophođenom promjenu #"
   const msg_patrol_successful = window.ip_msg_patrol_successful || "Patrolling revision #"; //pop-up notification; hr:"Ophodim izmjenu "
   const msg_patrol_error = window.ip_msg_patrol_error || "Error patrolling revision #"; //pop-up notification; hr:"Pogreška u ophodnji izmjene "
   const no_excl = !window.ip_show_exclamation_marks && true; // should red exclamation marks still be shown in RC

   mw.util.addCSS( '.ip-button {font-weight:bold;} .ip-button:hover {cursor:pointer;} .ip-unpatrolled {color:#a11;} .ip-patrolled {color:#ddd;} .ip-error {color:#d96;}' );

   //------------------------------------ RECENT CHANGES page

   if (mw.config.get("wgCanonicalSpecialPageName") === "Recentchanges") {
      //exclamation marks for unpatrolled changes already present; add [patrol] buttons, populate with revid data, add onclick handler

      function setupRC() {
         $("abbr.unpatrolled").each(function() {
            let parent = $(this).parents(".mw-changeslist-line")
            let revid = parent.attr("data-mw-revid")
            if (revid) {
               let pmark = $('<span>')
               pmark.attr("class", "ip-button ip-unpatrolled")
                    .text(" ["+msg_patrol+"] ")
                    .attr("title", msg_patrol_hint + revid)
                    .data("revid", revid)
                    .on("click", qmClick);
               pmark.insertAfter(parent.find("span.mw-changeslist-separator").eq(0));
               if (no_excl) {$(this).css("display","none");}
            }
            parent.css("background-color", "#fee") //lightred
         });

      } //function setupRC

      setupRC();

      //mw.hook because RC page likes to update itself
      mw.hook("wikipage.content").add(function(el) {
         if (el.hasClass('mw-changeslist')) {
            setupRC();
         }
      });

   } // if Recentchanges


   //------------------------------------ PAGE HISTORY and USER CONTRIBUTION pages

   let uc_ph = "" //user contributions or page history

   if (mw.config.get("wgCanonicalSpecialPageName") === "Contributions") {
      var rcKey = "rcuser";
      var rcValue = mw.config.get("wgRelevantUserName");
      uc_ph = "uc";
   }

   if (mw.config.get("wgAction") === "history") {
      var rcKey = "rctitle";
      var rcValue = mw.config.get("wgPageName");
      uc_ph = "ph";
   }

   if (uc_ph != "") {

      //get unpatrolled user edits or unpatrolled page edits
      const unpatrolledRevisionsPromise = new mw.Api().get({
         "action": "query",
         "format": "json",
         "list": "recentchanges",
         "rcprop": "ids|patrolled",
         "rcshow": "unpatrolled",
         "rclimit": "123",
         [rcKey]: rcValue //mdn: computed property names
      });


      //add [patrol] buttons, populate each with revid data, add onclick handler
      unpatrolledRevisionsPromise.done(function(jsondata) {
         $.each(jsondata.query.recentchanges, function(i, rc) {
            //console.log(rc.revid);
            let parent = $("li[data-mw-revid=" + rc.revid + "]")
            let pmark = $('<span>')
            pmark.attr("class", "ip-button ip-unpatrolled")
                 .text(" ["+msg_patrol+"] ")
                 .attr("title", msg_patrol_hint + rc.revid)
                 .data("revid", rc.revid)
                 .on("click", qmClick)
            pmark.insertAfter(parent.find("span.mw-changeslist-separator").eq(0))
            parent.css("background-color", "#fee"); //lightred
         })

      }); // .done()  
   } // if Contributions or History (uc_ph)



   //------------------------------------ HELPER FUNCTIONS (hoisted)

   //mw.Api patrol call
   function patrol(revid) {
      console.log("(inline-patrol) patrolling revid ", revid);
      mwPromise = new mw.Api().postWithToken('patrol', {
         'action': 'patrol',
         'format': 'json',
         'revid': revid
      });
      return mwPromise;
   }


   //[patrol] button click handler
   function qmClick(event) {
      const revid = $(this).data().revid; //"this" is the calling object
      const mwPromise = patrol(revid);

      mwPromise.done((data) => { //arrow function does not create its context, "this" is from outer context
         mw.notify(msg_patrol_successful + revid);
         $(this)
            .removeClass("ip-unpatrolled").addClass("ip-patrolled")
            .off(); //no clicks
      });

      mwPromise.fail((data) => { //arrow function does not create its context, "this" is from outer context
         mw.notify(msg_patrol_error + revid);
         $(this)
            .removeClass("ip-unpatrolled").addClass("ip-error")
            .off(); //no clicks
      });

      event.stopPropagation();
      return false;
   }


}); // if document ready