User:MusikAnimal/userRightsManager.js: Difference between revisions

Content deleted Content added
No edit summary
small fix to add a template that can be placed on a user's talk page when TAIV is granted (again should be relatively uncontroversial as a change, so actioning it on my own) -- folks (other intadmins or MusikAnimal) are welcomed to revert me if they disagree :)
 
(34 intermediate revisions by 3 users not shown)
Line 2:
// Some UI code adapted from [[User:Mr. Stradivarius/gadgets/Draftify.js]]
(function() {
if (!/Wikipedia:Requests for permissions\//.test(document.title)) {
return;
}
 
var permissionNames = {
'Account creator': 'accountcreator',
'Autopatrolled': 'autoreviewer',
'Confirmed': 'confirmed',
'Event coordinator': 'eventcoordinator',
'File mover': 'filemover',
'Extended confirmed': 'extendedconfirmed',
'Mass message sender': 'massmessage-sender',
'File mover': 'filemover',
'Pending changes reviewer': 'reviewer',
'Mass message sender': 'massmessage-sender',
'Rollback': 'rollbacker',
'New page reviewer': 'patroller',
'Template editor': 'templateeditor'
'Page mover': 'extendedmover',
};
'Pending changes reviewer': 'reviewer',
'Rollback': 'rollbacker',
'Template editor': 'templateeditor',
'Temporary account IP viewer': 'temporary-account-viewer',
};
 
var templates = {
'Account creator': 'Account creator granted',
'Autopatrolled': 'Autopatrolledgiven',
'AutoWikiBrowser': '',
'Confirmed': '',
'Event coordinator': 'Event coordinator granted',
'File mover': 'Filemovergiven',
'Extended confirmed': '',
'Mass message sender': 'Mass message sender granted',
'File mover': 'Filemovergiven',
'Pending changes reviewer': 'Pending changes reviewer granted',
'Mass message sender': 'Mass message sender granted',
'Rollback': 'Rollbackgiven3',
'New page reviewer'Template: editor':New 'TemplatePage editorReviewer granted',
'Page mover': 'Page mover granted',
};
'Pending changes reviewer': 'Pending changes reviewer granted',
'Rollback': 'Rollback granted 3',
'Template editor': 'Template editor granted',
'Temporary account IP viewer': 'Temporary account IP viewer granted',
};
 
var api = new mw.Api(),
permission = mw.config.get('wgTitle').split('/').slice(-1)[0],
revisionId = mw.config.get('wgRevisionId'),
tagLine = ' (using [[User:MusikAnimal/userRightsManager.js|userRightsManager]])',
permaLink, userName, dialog;
 
mw.loader.using(['oojs-ui', 'mediawiki.api', 'mediawiki.widgets.DateInputWidget'], function() {
api = new mw.Api();
$('.sysop-show a').on('click', function(e) {
$('.perm-assign-permissions a').on('click', function(e) {
if (permission === 'AutoWikiBrowser') return true;
if (permission === 'AutoWikiBrowser') return true;
e.preventDefault();
e.preventDefault();
userName = $(this).parents('.plainlinks').find('a').eq(0).text();
userName = $(this).parents('.plainlinks').find('a').eq(0).text();
permaLink = '[[Special:PermaLink/' + revisionId + '#User:' + userName + ']]';
showDialog();
});
});
 
function showDialog() {
Dialog = function(config) {
Dialog.super.call(this, config);
this.hasBeenSubmitted = false;
};
Dialog.super.call(this, config);
OO.inheritClass(Dialog, OO.ui.ProcessDialog);
};
Dialog.static.name = 'user-rights-manager';
OO.inheritClass(Dialog, OO.ui.ProcessDialog);
Dialog.static.title = 'Grant ' + permission + ' to ' + userName;
Dialog.static.actions = [
{ action: 'submit', label: 'Submit', flags: ['primary', 'constructive'] },
{ label: 'Cancel', flags: 'safe' }
];
Dialog.prototype.getApiManager = function() {
return this.apiManager;
};
Dialog.prototype.getBodyHeight = function() {
return 120208;
};
Dialog.prototype.initialize = function() {
Dialog.super.prototype.initialize.call( this );
this.editFieldset = new OO.ui.FieldsetLayout( {
classes: ['container']
});
this.editPanel = new OO.ui.PanelLayout({
expanded: false
});
this.editPanel.$element.append( this.editFieldset.$element );
this.rightsChangeSummaryInput = new OO.ui.TextInputWidget({
value: 'Requested at [[WP:PERM]]; ' + permaLink
});
this.closingRemarksInputexpiryInput = new OOmw.uiwidgets.TextInputWidgetDateInputWidget({
$overlay: $('.oo-ui-window')
value: '{{done}} ~~~~'
});
this.closingRemarksInput = new OO.ui.TextInputWidget({
this.editFieldset.addItems( [
value: '{{done}} ~~~~'
new OO.ui.FieldLayout( this.rightsChangeSummaryInput, {
});
label: 'Summary'
this.watchTalkPageCheckbox = new OO.ui.CheckboxInputWidget({
} ),
selected: false
new OO.ui.FieldLayout( this.closingRemarksInput, {
});
label: 'Closing remarks'
var formElements = [
} )
new OO.ui.FieldLayout(this.rightsChangeSummaryInput, {
] );
label: 'Summary'
this.submitPanel = new OO.ui.PanelLayout( {
}),
$: this.$,
new OO.ui.FieldLayout(this.expiryInput, {
expanded: false
label: 'Expiry (optional)'
} );
}),
this.submitFieldset = new OO.ui.FieldsetLayout( {
new OO.ui.FieldLayout(this.closingRemarksInput, {
classes: ['container']
label: 'Closing remarks'
} );
})
this.submitPanel.$element.append( this.submitFieldset.$element );
];
this.changeRightsProgressLabel = new OO.ui.LabelWidget();
if (!!templates[permission]) {
this.changeRightsProgressField = new OO.ui.FieldLayout( this.changeRightsProgressLabel );
formElements.push(
this.markAsDoneProgressLabel = new OO.ui.LabelWidget();
this.markAsDoneProgressField = new OO.ui.FieldLayout( this.markAsDoneProgressLabelwatchTalkPageCheckbox, );{
label: 'Watch user talk page'
this.issueTemplateProgressLabel = new OO.ui.LabelWidget();
})
this.issueTemplateProgressField = new OO.ui.FieldLayout( this.issueTemplateProgressLabel );
);
this.stackLayout = new OO.ui.StackLayout( {
}
items: [this.editPanel, this.submitPanel],
this.editFieldset.addItems(formElements);
padded: true
this.submitPanel = new OO.ui.PanelLayout( {
} );
$: this.$,
this.$body.append( this.stackLayout.$element );
expanded: false
};
} );
this.submitFieldset = new OO.ui.FieldsetLayout( {
classes: ['container']
} );
this.submitPanel.$element.append( this.submitFieldset.$element );
this.changeRightsProgressLabel = new OO.ui.LabelWidget();
this.changeRightsProgressField = new OO.ui.FieldLayout( this.changeRightsProgressLabel );
this.markAsDoneProgressLabel = new OO.ui.LabelWidget();
this.markAsDoneProgressField = new OO.ui.FieldLayout( this.markAsDoneProgressLabel );
this.issueTemplateProgressLabel = new OO.ui.LabelWidget();
this.issueTemplateProgressField = new OO.ui.FieldLayout( this.issueTemplateProgressLabel );
this.stackLayout = new OO.ui.StackLayout( {
items: [this.editPanel, this.submitPanel],
padded: true
} );
this.$body.append( this.stackLayout.$element );
$( '.mw-widget-dateInputWidget' ).css( 'width', '100%' );
};
 
Dialog.prototype.getReadyProcessonSubmit = function( data ) {
var self = this, promiseCount = !!templates[permission] ? 3 : 2;
data = data || {};
return Dialog.super.prototype.getReadyProcess.call( this, data ).next( function() {
if ( this.hasBeenSubmitted ) {
this.actions.setAbilities( { submit: false } );
}
}, this );
};
 
self.actions.setAbilities( { submit: false } );
Dialog.prototype.onSubmit = function() {
var self = this;
 
addPromise = function( field, promise ) {
self.hasBeenSubmitted = true; // FIXME: may not need this
self.pushPending();
self.actions.setAbilities( { submit: false } );
promise.done(function() {
field.$field.append( $( '<span>' )
.text( 'Complete!' )
.prop('style', 'position:relative; top:0.5em; color: #009000; font-weight: bold')
);
}).fail(function(obj) {
if ( obj && obj.error && obj.error.info ) {
field.$field.append( $( '<span>' )
.text('Error: ' + obj.error.info)
.prop('style', 'position:relative; top:0.5em; color: #cc0000; font-weight: bold')
);
} else {
field.$field.append( $( '<span>' )
.text('An unknown error occurred.')
.prop('style', 'position:relative; top:0.5em; color: #cc0000; font-weight: bold')
);
}
}).always( function() {
promiseCount--; // FIXME: maybe we could use a self.isPending() or something
self.popPending();
 
if (promiseCount === 0) {
var promises = [
setTimeout(function() {
assignPermission(this.rightsChangeSummaryInput.getValue() + tagLine),
___location.reload(true);
markAsDone('\n::' + this.closingRemarksInput.getValue()),
}, 1000);
issueTemplate()
}
];
});
 
return promise;
addField = function( field, label, promise ) {
};
if ( !promise ) return;
self.pushPending();
field.setLabel( label );
self.submitFieldset.addItems( [field] );
promise.done(function() {
field.$field.append( $( '<span>' )
.text( 'Complete!' )
.prop('style', 'position:relative; top:0.5em; color: #009000; font-weight: bold')
);
}).fail(function( id, obj ) {
if ( obj && obj.error && obj.error.info ) {
field.$field.append( $( '<span>' )
.text('Error: ' + obj.error.info)
.prop('style', 'position:relative; top:0.5em; color: #cc0000; font-weight: bold')
);
} else {
field.$field.append('An unknown error occurred.');
}
}).always( function() {
self.popPending();
});
};
 
self.markAsDoneProgressField.setLabel( 'Marking request as done...' );
addField(
self.submitFieldset.addItems( [self.markAsDoneProgressField] );
self.changeRightsProgressField,
self.changeRightsProgressField.setLabel( 'Assigning rights...', );
self.submitFieldset.addItems( [self.changeRightsProgressField] );
promises[0]
);
if (!!templates[permission]) {
addField(
self.issueTemplateProgressField.setLabel( 'Issuing template...' );
self.issueTemplateProgressField,
self.submitFieldset.addItems( [self.issueTemplateProgressField] );
'Issuing template...',
}
promises[1]
);
addField(
self.markAsDoneProgressField,
'Marking request as done...',
promises[2]
);
 
addPromise(
$.when(promises).done( function() {
self.markAsDoneProgressField,
setTimeout(function() {
markAsDone('\n:' + this.closingRemarksInput.getValue())
___location.reload(true);
).then(function(data) {
}, 2000);
addPromise(
});
self.changeRightsProgressField,
$.when(promises).fail( function() {
assignPermission(
self.popPending();
this.rightsChangeSummaryInput.getValue(),
} );
data.edit.newrevid,
self.stackLayout.setItem( self.submitPanel );
this.expiryInput.getValue()
};
)
).then(function() {
// silently add user to MMS list
if (permission === 'New page reviewer') {
addToMMSList();
} else if (permission === 'Autopatrolled') {
updateWhiteList();
}
 
if (!!templates[permission]) {
Dialog.prototype.getActionProcess = function( action ) {
addPromise(
return Dialog.super.prototype.getActionProcess.call( this, action ).next( function() {
self.issueTemplateProgressField,
if ( action === 'submit' ) {
issueTemplate(this.watchTalkPageCheckbox.isSelected(), this.expiryInput.getValue())
return this.onSubmit();
);
} else {
}
return Dialog.super.prototype.getActionProcess.call( this, action );
}.bind(this));
}
}, .bind(this ));
};
 
self.stackLayout.setItem( self.submitPanel );
dialog = new Dialog({
};
size: 'medium'
});
 
Dialog.prototype.getActionProcess = function( action ) {
var windowManager = new OO.ui.WindowManager();
return Dialog.super.prototype.getActionProcess.call( this, action ).next( function() {
$('body').append(windowManager.$element);
if ( action === 'submit' ) {
windowManager.addWindows([dialog]);
return this.onSubmit();
windowManager.openWindow(dialog);
} else {
}
return Dialog.super.prototype.getActionProcess.call( this, action );
}
}, this );
};
 
dialog = new Dialog({
function assignPermission(summary) {
size: 'medium'
return api.postWithToken( 'userrights', {
});
action: 'userrights',
format: 'json',
user: userName,
add: permissionNames[permission],
reason: summary
});
}
 
var windowManager = new OO.ui.WindowManager();
function markAsDone(closingRemarks) {
$('body').append(windowManager.$element);
var sectionNode = document.getElementById('User:' + userName),
windowManager.addWindows([dialog]);
sectionNumber = $(sectionNode).siblings('.mw-editsection').find('a').prop('href').match(/section=(\d)/)[1];
windowManager.openWindow(dialog);
return api.postWithToken( 'edit', {
}
format: 'json',
action: 'edit',
title: mw.config.get('wgPageName'),
section: sectionNumber,
summary: 'done' + tagLine,
appendtext: closingRemarks
} );
}
 
function issueTemplateassignPermission(optionssummary, revId, expiry) {
permaLink = '[[Special:PermaLink/' + revId + '#User:' + userName + '|permalink]]';
options = options || {};
return api.postWithToken( 'edituserrights', {
action: 'userrights',
format: 'json',
action format: 'editjson',
user: userName.replace(/ /g, '_'),
title: 'User talk:' + userName,
add: permissionNames[permission],
section: 'new',
reason: '+' + permissionNames[permission] + '; summary: permission' + 'summary granted+ per'; ' + permaLink + tagLine,
expiry: expiry === '' ? 'infinity' : expiry
text: '{{subst:' + templates[permission] + '}}',
});
sectiontitle: permission + ' granted',
}
watchlist: options.watch ? 'watch' : 'unwatch'
 
} );
function markAsDone(closingRemarks) {
}
var sectionNode = document.getElementById('User:' + userName.replace(/"/g, '.22').replace(/ /g, '_')),
sectionNumber = $(sectionNode).siblings('.mw-editsection').find("a:not('.mw-editsection-visualeditor')").prop('href').match(/section=(\d+)/)[1];
return api.postWithToken( 'edit', {
format: 'json',
action: 'edit',
title: mw.config.get('wgPageName'),
section: sectionNumber,
summary: '/* User:' + userName + ' */ done' + tagLine,
appendtext: closingRemarks
});
}
 
function issueTemplate(watch, expiry) {
var talkPage = 'User talk:' + userName.replace(/ /g, '_');
return api.postWithToken( 'edit', {
format: 'json',
action: 'edit',
title: talkPage,
section: 'new',
summary: permission + ' granted per ' + permaLink + tagLine,
text: '{{subst:' + templates[permission] + (expiry === '' ? '' : '|expiry=' + expiry) + '}}',
sectiontitle: permission + ' granted',
watchlist: watch ? 'watch' : 'unwatch'
});
}
function addToMMSList() {
api.postWithToken( 'csrf', {
format: 'json',
action: 'editmassmessagelist',
spamlist: 'Wikipedia:New pages patrol/Reviewers/Newsletter list',
add: 'User talk:' + userName
});
}
function updateWhiteList() {
api.edit( 'Wikipedia:New pages patrol/Redirect autopatrol list', function (revision) {
var newContent = revision.content.replace(
new RegExp('\\*\\s*{{\\s*user2\\s*\\|\\s*' + userName + '\\s*}}\\n'),
''
);
return {
text: newContent,
summary: 'Removing ' + userName + ' who is now autopatrolled' + tagLine,
minor: true
};
});
}
})();
// </nowiki>