User:Jon Harald Søby/PermissionOTRS.js
Jump to navigation
Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
Documentation for this user script can be added at User:Jon Harald Søby/PermissionOTRS. |
- Report page listing warnings and errors.
/** PermissionOTRS.js
// Adds OTRS permission template via the API. Other templates such as {OTRS pending} will be removed.
* @revision 20:10, 7 June 2017 (UTC)
* @license: under the terms of the MIT license
* @authors:
* Maintainer: [[User:Rillke]]
* Created by Bryan Tong Minh
* Amended by [[:de:User:DerHexer]], [[User:Guandalug]], DieBuche, [[User:Steinsplitter]]
* Partially rewritten by Perhelion
* @required modules: mediawiki.util, jquery.ui, mediawiki.api
// <nowiki>
**/
/*global mediaWiki, jQuery*/
/*jshint curly:false, scripturl:true, forin:false*/
var init = (function ($, mw, OO) {
'use strict';
var user = mw.config.get('wgUserName'),
uGrp = mw.config.get('wgUserGroups'),
sLink = '([[MediaWiki:Gadget-PermissionOTRS.js|Script]]) [[COM:OTRS|OTRS]] ',
page = mw.config.get('wgPageName'),
ticket,
edittoken,
content,
timestamp,
reason;
if (mw.config.get('wgNamespaceNumber') !== 6 || $.inArray('autoconfirmed', uGrp) === -1 || !user)
return;
var editform = (!mw.config.get('wgIsArticle')) ? document.editform : null;
// NEW STUFF
function OTRSdialog(config) {
OTRSdialog.parent.call(this, config);
}
OO.inheritClass(OTRSdialog, OO.ui.ProcessDialog);
OTRSdialog.static.name = 'otrsdialog';
OTRSdialog.static.title = 'OTRS';
OTRSdialog.static.size = 'small';
OTRSdialog.static.actions = [
{
action: 'ok',
label: mw.msg( 'ooui-dialog-message-accept' ),
flags: ['primary', 'constructive']
},
{
action: 'cancel',
label: mw.msg( 'ooui-dialog-message-reject' ),
flags: 'safe',
}
];
OTRSdialog.prototype.initialize = function() {
OTRSdialog.parent.prototype.initialize.apply(this, arguments);
var OTRSnumber = '';
var fieldset = new OO.ui.FieldsetLayout({});
this.OTRSfield = new OO.ui.TextInputWidget({
value: this.OTRSnumber
});
fieldset.addItems([
new OO.ui.FieldLayout(
this.OTRSfield,
{
align: 'left',
label: 'Ticket ID (16 digit number):'
}
)
]);
};
// /NEW STUFF
function _prompt(text, OTRS) {
var OTRSfield = $('#field-otrs'), // there is already a ticket
name = 'OTRS',
$select;
if (OTRSfield.length) // try pre-fill the ticket
ticket = OTRSfield.attr('title').replace(/[^\n]+(\d{16})$/, '$1');
else if (editform && /\{\{otrs[ _]received\|id=(\d{16})+[^\}\n]*\}\}/i.test(editform.wpTextbox1.value))
ticket = RegExp.$1;
var type = 'errorbox',
title = (OTRS && OTRS.name) ? OTRS.name : name,
$reason = $('<br>'),
$ticket = $('<input>').attr({
'value': ticket,
'type': 'text',
'id': name + 'dialog',
'maxlength': 23, // for possible pre-phrase "Ticket#"
'size': 17,
'class': 'numbersOnly'
});
if (title === 'OTRSreceived') {
$select = $('<select>').attr({
'id': name + 'combo'
});
reason = $('<input>').attr({
'type': 'checkbox',
'id': name + 'reason'
}).on('change', function(){
$select.toggle();
});
$reason = $reason.add(reason.add($('<label>').attr({
'for': name + 'reason',
'style': 'margin-right:.5em;line-height:1.5em',
}).text('Give a reason?')
));
$.each(['processing', 'licence', 'email'], function (i, el) {
$select.append($('<option>').text(el));
});
$reason = $reason.add($select.hide());
}
if (!text) {
title = 'INVALID ID';
text = 'You must enter a valid 16-digit ticket number.';
} else if (text === 'FAIL') {
title = text;
text = 'No suitable place found to insert template! Please add the template by hand.';
$ticket = '';
} else
type = '';
text = $('<label>').attr({
'for': name + 'dialog',
'style': 'margin-right:0.4em',
'class': type
}).text(text);
$('<div>').append([text, $ticket, $reason]).dialog({
width: 400,
dialogClass: 'wikiEditor-toolbar-dialog',
resizable: false,
modal: true,
title: title,
close: function () {
$(this).dialog('destroy');
$(this).remove();
},
buttons: [{
text: 'OK',
click: function () {
ticket = ($ticket) ? $.trim($ticket.val()).replace(/^(Ticket)?#/, '') : ''; // cleanup input
$(this).dialog('close');
if (ticket) { // Check ticket validity
if (reason)
reason = (reason.prop( 'checked'))? $select.find('option:selected').text() : '';
if (/^\d{16}$/.test(ticket))
return _getPage(OTRS);
_prompt('', OTRS);
}
}
}
]
});
}
function _addPermission(template, summary) {
var text = _cleanUp(content),
text_before = text,
regP = /( )*\|\s*[Pp]ermission( )*\=\s*([^\n]*\n)/,
regA = /( )*\|\s*[Aa]uthor( )*\=\s*[^\n]*\n/g; // fallback position, if no permission parameter
if (!regP.test(text)) {
if (!regA.test(text))
return _prompt('FAIL');
var l = regA.lastIndex,
s1 = RegExp.$1 || "", // leading whitespaces as indent?
s2 = (RegExp.$2) ? " " : "", // whitespace on parameter?
sr = text.substr(l).search(/^\s*(\||\}\})/m); // try to got at template end
if (sr >= 0) {
sr += l; // insert to the end of information template
text = text.substr(0, sr) + s1 + "|permission" + s2 + "=" + s2 + template + "\n" + text.substr(sr);
} else
return _prompt('FAIL');
} else {
if (text.indexOf(template) > 0)
return mw.notify('Same ticket already added…', {
title: 'OTRS fail…',
type: 'warn'
});
text = text.replace(regP, "$1|permission$2=$2" + template + "\n$3");
}
if (text_before === text)
return _prompt('FAIL');
content = text;
_savePage(sLink + summary);
}
var PermissionOTRS = function PermissionOTRS() {
_addPermission('{{PermissionOTRS|id=' + ticket + "|user=" + user + "}}",
'permission added');
};
var OTRSreceived = function OTRSreceived() {
_addPermission('{{OTRS received|id=' + ticket +
'|year={{subst:' +
'#time:Y}}|month={{subst:' +
'#time:F}}|day={{subst:' +
'#time:j}}' + (reason? '|reason=' + reason : '' ) +
'|user=' + user + '}}',
'email received but not processed yet');
};
function _cleanUp(text) {
// ToDo: maybe here could be loaded another general cleanup module!?
return $.trim(text
.replace(/\=\= ?Summary ?\=\=/, '=={{int:filedesc}}==')
.replace(/\=\= ?Licensing ?\=\=/, '=={{int:license-header}}==')
.replace(/\{\{OTRS[ _\-](pending|received)[^\}\n]*\}\}\s?/ig, '')
.replace(/\{\{[Nn]o[ _](OTRS[ _])?permission[^\}\n]*\}\}\s*/g, '\n')
.replace(/\{\{[Dd]elete[^\}\n]*\}\}\s?/g, ''));
}
function _apiFail(code, r) {
if (!code.indexOf("http")) {
console.log("HTTP error: " + r.textStatus);
} else if (code === "ok-but-empty") {
console.log("Got an empty response from the server");
} else {
console.log("API error: " + code);
}
mw.notify('There was an error processing your request.\n\t\t\t API-error-code:' +
code + '\n\n\t\t\t\tPlease try again.', {
title: 'Error!',
autoHide: 0,
type: 'error'
});
}
function _getPage(OTRS) {
if (!editform) {
mw.notify('…request to tag with "' + OTRS.name + '"\n with Ticket#: ' + ticket, {
title: 'Processing…'
});
new mw.Api().get({
prop: "info|revisions",
meta: "tokens",
rvprop: "content|timestamp",
titles: page
}).done(function (r) {
mw.notify('Got page contents…', {
title: 'Processing…'
});
r = r.query;
var pages = r.pages;
var tokens = r.tokens;
if (tokens.hasOwnProperty("csrftoken"))
edittoken = tokens.csrftoken;
for (var id in pages) {
if (pages.hasOwnProperty(id)) {
pages = pages[id];
content = pages.revisions[0]['*'];
timestamp = pages.revisions[0].timestamp;
return OTRS();
}
}
}).fail(function (code, r) {
_apiFail(code, r);
});
} else {
content = editform.wpTextbox1.value;
return OTRS();
}
}
function doneMsg() {
return mw.notify('OTRS ticket successfully inserted.', {
title: 'Done!'
});
}
function _savePage(summary) {
if (!editform) {
new mw.Api().post({
action: 'edit',
summary: summary,
watchlist: 'preferences', // or nochange?
title: page,
token: edittoken,
text: content,
notminor: 1
}).done(function () {
doneMsg().done(function () {
location.reload();
});
}).fail(function (code, r) {
_apiFail(code, r);
});
} else {
editform.wpMinoredit.checked = false;
editform.wpTextbox1.value = content;
var sum = editform.wpSummary;
sum.value = $.trim(sum.value.replace(summary, "") + " " + summary);
doneMsg();
}
}
function dialogOTRS(e, OTRS) {
e.preventDefault();
function chkuGrp(b) {
if (!b)
return mw.notify('You are not authorized for this function!', {
title: 'OTRS fail!',
type: 'warn'
});
_prompt('Ticket ID (16 digit number):', OTRS);
}
if ($.inArray('OTRS-member', mw.config.get('wgGlobalGroups')) > -1 || $.inArray('sysop', uGrp) > -1)
chkuGrp(1);
else // run only for non-admin but 'OTRS-member'
new mw.Api().get({
meta: "globaluserinfo",
guiuser: user,
guiprop: "groups",
}).done(function (r) {
chkuGrp(($.inArray('OTRS-member', r.query.globaluserinfo.groups) > -1));
}).fail(function (code, r) {
_apiFail(code, r);
});
}
var bReceive, bConfirm; // booleans; add link only if needed
$('#mw-hidden-catlinks li').children('a').each(function () {
if (this.text && !(bReceive && bConfirm)) { // check cats
if (/^Items with (?:ticket )?OTRS permission confirmed/.test(this.text))
bConfirm = bReceive = 1;
else if (/^OTRS received/.test(this.text))
bReceive = 1;
}
});
mw.loader.using(['mediawiki.util', 'jquery.ui', 'mediawiki.api'], function () {
if (!bConfirm) {
$(mw.util.addPortletLink('p-tb', '#', 'Permission OTRS (BETA)'))
.on('click', function (e) {
dialogOTRS(e, PermissionOTRS);
});
if (!bReceive)
$(mw.util.addPortletLink('p-tb', '#', 'OTRS received (BETA)'))
.on('click', function (e) {
dialogOTRS(e, OTRSreceived);
});
}
});
});
mw.loader.using(['oojs-ui']).then(function() {
init(jQuery, mediaWiki, OO)
});
// EOF </nowiki>