Wikipedysta:Nadzik/Gadget-move-to-sandbox.js
/* global mw, jQuery, moveToSandboxGadget */
/* Translatable strings */
mw.messages.set( {
'mtsg-anonymous-author-sandbox-account': 'Wikipedysta:Brudnopis gościnny',
'mtsg-move-link': 'Przenieś do brudnopisu',
'mtsg-user-talk-link': 'dyskusja',
'mtsg-user-contribs-link': 'wkład',
'mtsg-dialog-title': 'Przenieś do brudnopisu',
'mtsg-author-label': 'Autor artykułu:',
'mtsg-author-pending': 'sprawdzanie',
'mtsg-destination-label': 'Docelowa nazwa artykułu:',
'mtsg-reason-label': 'Uzasadnienie:',
'mtsg-default-reason': 'artykuł należy dopracować',
'mtsg-message-label': 'Wiadomość dla użytkownika:',
'mtsg-error-label': 'Błąd:',
'mtsg-jobs-label': 'Wykonywane zadania:',
'mtsg-default-message': 'Witaj. Twój artykuł nie nadaje się jeszcze do publikacji w Wikipedii, dlatego został przeniesiony do twojego \'\'\'[[$link|brudnopisu]]\'\'\', gdzie możesz nad nim popracować. Popraw w nim:\n* ...\n* ...\n* ...\n* ...\n\nW razie problemów skorzystaj z [[Pomoc:Jak napisać nowy artykuł|tego poradnika]], zadaj pytanie na [[Pomoc:Pytania nowicjuszy|tej stronie]] lub spytaj [[Pomoc:Przewodnicy|przewodników]].\n\nPo skończeniu użyj [[Pomoc:Zmiana nazwy strony|zakładki „Przenieś”]], aby ponownie opublikować artykuł. Jeżeli nie masz takiej zakładki (należy mieć konto zarejestrowane od co najmniej 4 dni oraz 10 edycji), napisz na [[Pomoc:Pytania nowicjuszy|tej stronie]] lub zwróć się do [[Pomoc:Przewodnicy|przewodników]].',
'mtsg-additional-information-for-anonymous': '\n\nZapisz sobie podany adres strony, aby nie mieć problemu z powrotem do niej.',
'mtsg-signature': '\n\nPozdrawiam, ~~' + '~~',
'mtsg-confirm-button': 'Przenieś',
'mtsg-cancel-button': 'Anuluj',
'mtsg-move-page-job': 'Przenoszenie strony',
'mtsg-insert-speedy-job': 'Wstawianie szablonu ek do przekierowania',
'mtsg-send-message-job': 'Wysyłanie wiadomości autorowi',
'mtsg-redirect-job': 'Przejście na stronę po przenosinach',
'mtsg-speedy-template': '{' + '{ek|1=strona została przeniesiona do [[$1|brudnopisu autora]]))\n',
'mtsg-speedy-summary': 'Oznaczenie przekierowania po przenosinach do skasowania',
'mtsg-edit-article': 'Sprzątanie artykułu w brudnopisie (wyłączanie kategoryzacji, EK i DNU)',
'mtsg-block-categorization-summary': 'Wyłączono kategoryzację brudnopisu',
'mtsg-remove-tpl-summary': 'Usunięto szablon %tpl% z brudnopisu',
'mtsg-error-nonexistent-page': 'Artykuł nie istnieje.',
'mtsg-error-unknown-author': 'Nie można określić autora artykułu.',
'mtsg-error-no-move-permission': 'Nie masz uprawnień do przenoszenia stron.',
'mtsg-error-empty-destination-name': 'Nazwa strony docelowej nie może być pusta.',
'mtsg-error-move-message-not-changed': 'Uzupełnij wiadomość do użytkownika.',
'mtsg-error-move-message-not-changed-reasons': 'Usuń te puste punkty z kropkami jak nie ma więcej powodów; to wygląda dziwnie...',
'mtsg-error-caught-exception': 'Wystąpił błąd podczas działania gadżetu. Przekaż następujące informacje autorowi:',
'mtsg-error-api-error': 'Operacja się nie powiodła'
} );
window.moveToSandboxGadget = {
/** Version of the gadget */
version: 8.1,
/* Gadget variables */
canSuppressRedirect: false,
token: null,
moveSource: mw.config.get( 'wgPageName' ).replace( /_/g, ' ' ),
moveDestination: null,
moveReason: null,
author: null,
jobQueue: [],
currentJob: null,
debug: false,
api: new mw.Api(),
/** Gadget entry point */
init: function() {
if ( mw.config.get( 'wgNamespaceNumber' ) !== 0 || mw.config.get( 'wgArticleId' ) === 0 ) {
return;
}
var that = this;
jQuery( document ).ready( function() {
that.addMenu();
} );
},
/** Adds menu for triggering dialog box */
addMenu: function() {
var that = this;
mw.util.addPortletLink( 'p-tb', '', mw.msg( 'mtsg-move-link' ), 'move-to-sandbox' );
jQuery( '#move-to-sandbox a' ).click( function( event ) {
that.open();
event.preventDefault();
} ).attr( 'href', '#' );
},
/** Shows dialog box */
open: function() {
var dialog = jQuery('<div></div>').append(
'<form>' +
'<fieldset id="mtsg-fieldset">' +
'<label for="mtsg-author">' + mw.msg( 'mtsg-author-label' ) + '</label>' +
'<span id="mtsg-author" class="text ui-widget-content ui-corner-all">' + mw.msg( 'mtsg-author-pending' ) + '</span>' +
'<label for="mtsg-destination">' + mw.msg( 'mtsg-destination-label' ) + '</label>' +
'<input type="text" name="mtsg-destination" id="mtsg-destination" class="text ui-widget-content ui-corner-all" disabled="disabled"/>' +
'<label for="mtsg-reason">' + mw.msg( 'mtsg-reason-label' ) + '</label>' +
'<input type="text" name="mtsg-reason" id="mtsg-reason" class="text ui-widget-content ui-corner-all" value="' + mw.msg( 'mtsg-default-reason' ) + '"/>' +
'<label for="mtsg-message">' + mw.msg( 'mtsg-message-label' ) + '</label>' +
'<textarea rows="3" name="mtsg-message" id="mtsg-message" class="text ui-widget-content ui-corner-all mtsg-message-full"></textarea>' +
'<a class="sandbox_msg_snippets" data-snip="Dodaj [[WP:WER|przypisy]]">Przypisy</a> <a class="sandbox_msg_snippets" data-snip="Popraw [[Pomoc:Formatowanie|formatowanie]]">Format</a> <a class="sandbox_msg_snippets" data-snip="Wykaż [[WP:ENCY|encyklopedyczność]]">ENCY</a> <a class="sandbox_msg_snippets" data-snip="Popraw tłumaczenie maszynowe">Tłumaczenie</a> <a class="sandbox_msg_snippets" data-snip="[[Pomoc:Jak napisać doskonały artykuł|Rozbuduj]] artykuł">Rozbuduj</a>' +
'</fieldset>' +
'</form>'
);
var buttons = {};
buttons[mw.msg( 'mtsg-cancel-button' )] = function() {
jQuery( this ).dialog( 'close' );
};
jQuery( dialog ).dialog( {
width: 600,
height: 600,
modal: true,
resizable: false,
draggable: true,
closeOnEscape: true,
dialogClass: 'moveToSandboxDialog',
title: mw.msg( 'mtsg-dialog-title' ),
close: function() {
jQuery( this ).dialog( 'destroy' );
jQuery( this ).remove();
},
buttons: buttons
} );
var that = this;
var request = {
action: 'query',
prop: 'revisions|info',
rvprop: 'user|userid',
rvdir: 'newer',
meta: 'userinfo',
uiprop: 'rights',
titles: mw.config.get( 'wgPageName' ),
rvlimit: 1,
};
this.callApi( request, function( data ) {
var page = data.query.pages[mw.config.get( 'wgArticleId' )];
if ( !page ) {
that.showError( mw.msg( 'mtsg-error-nonexistent-page' ) );
return;
}
var revision = page.revisions[0];
if ( !revision || !revision.user ) {
that.showError( mw.msg( 'mtsg-error-unknown-author' ) );
return;
}
jQuery('#mtsg-author').empty().append(
jQuery('<a></a>').attr('href', mw.util.getUrl('User:' + revision.user)).append(document.createTextNode(revision.user)),
' (',
jQuery('<a>' + mw.msg( 'mtsg-user-talk-link' ) + '</a>').attr('href', mw.util.getUrl('User_talk:' + revision.user)),
', ',
jQuery('<a>' + mw.msg( 'mtsg-user-contribs-link' ) + '</a>').attr('href', mw.util.getUrl('Special:Contributions/' + revision.user)),
')'
);
var destUserName = mw.config.get( 'wgFormattedNamespaces' )[2] + ':' + revision.user;
if ( !revision.userid ) {
destUserName = mw.msg( 'mtsg-anonymous-author-sandbox-account' );
}
jQuery( '#mtsg-destination' ).attr( 'disabled', false ).val( destUserName + '/' + that.moveSource );
var userRights = data.query.userinfo.rights;
if ( jQuery.inArray( 'move', userRights ) == -1 ) {
that.showError( mw.msg( 'mtsg-error-no-move-permission' ) );
return;
}
that.canSuppressRedirect = jQuery.inArray( 'suppressredirect', userRights ) > -1;
that.author = revision.user;
var message = mw.message( 'mtsg-default-message' ).plain();
if ( revision.anon === "" ) {
message += mw.message( 'mtsg-additional-information-for-anonymous' ).plain();
}
message += mw.message( 'mtsg-signature' ).plain();
jQuery('#mtsg-message').val( message );
// Add confirm button
buttons[mw.msg( 'mtsg-confirm-button' )] = function() {
that.confirm( dialog );
};
jQuery( dialog ).dialog( "option", "buttons", buttons );
} );
jQuery('.sandbox_msg_snippets').click(function (event_data){
event_data.preventDefault();
jQuery('#mtsg-message').textSelection('encapsulateSelection', { pre: this.dataset.snip, replace: true });
});
},
/** Shows error on the dialog */
showError: function( message ) {
// Shrink the message field
jQuery( '#mtsg-message' ).removeClass( 'mtsg-message-full' );
jQuery( '#mtsg-fieldset' ).append( '<label for="mtsg-error">' + mw.msg( 'mtsg-error-label' ) + '</label>' );
jQuery( '#mtsg-fieldset' ).append( '<p id="mtsg-error">' + message + '</p>' );
this.updateCurrentStatus( 'error' );
},
updateCurrentStatus: function( status ) {
if ( !this.currentJob ) {
return;
}
if ( status == 'done' ) {
this.currentJob.image.src = '//upload.wikimedia.org/wikipedia/commons/thumb/d/df/OOjs_UI_icon_check.svg/16px-OOjs_UI_icon_check.svg.png';
} else if ( status == 'running' ) {
this.currentJob.image.src = '//upload.wikimedia.org/wikipedia/commons/3/32/Loader3.gif';
} else {
this.currentJob.image.src = '//upload.wikimedia.org/wikipedia/commons/thumb/1/18/OOjs_UI_icon_close-ltr.svg/16px-OOjs_UI_icon_close-ltr.svg.png';
}
},
/** Exception handler */
handleException: function( e ) {
var message = mw.msg( 'mtsg-error-caught-exception' ) + '\n' + e.name + ':' + e.message;
if ( e.stack ) {
message += '\n' + e.stack;
}
this.showError( message );
},
/** Creates list of jobs, and starts executing them */
processQueue: function() {
jQuery( '#mtsg-fieldset' ).append( '<label for="mtsg-jobs">' + mw.msg( 'mtsg-jobs-label' ) + '</label>' );
jQuery( '#mtsg-fieldset' ).append( '<div id="mtsg-jobs"></div>' );
// Shrink the message field
jQuery( '#mtsg-message' ).removeClass( 'mtsg-message-full' );
for ( var index in this.jobQueue ) {
var job = this.jobQueue[index];
var image = jQuery( '<img src="//upload.wikimedia.org/wikipedia/commons/1/11/Hourglass.png" width="16" height="16">' );
jQuery( '#mtsg-jobs' ).append( jQuery( '<div id="job-' + job.name + '"></div>' ).append( image, job.description ) );
job.image = image[0];
}
this.executeNextJob();
},
/** Executes next enqueued job */
executeNextJob: function() {
if ( this.currentJob ) {
this.updateCurrentStatus( 'done' );
}
if ( !this.jobQueue.length ) {
if ( this.debug ) {
console.log( 'There are no jobs left' );
}
return;
}
var that = this;
var job = this.jobQueue.shift();
if ( this.debug ) {
console.log( 'Executing job: ' + job.name );
console.log( job );
}
job.callback = function() {
that.executeNextJob();
};
job.owner = this;
this.currentJob = job;
this.updateCurrentStatus( 'running' );
try {
job.execute();
} catch ( e ) {
this.handleException( e );
}
},
/** Performs move */
confirm: function( dialog ) {
var gadget = this;
this.moveDestination = jQuery( '#mtsg-destination' ).val().trim();
if ( this.moveDestination == '' ) {
alert( mw.msg( 'mtsg-error-empty-destination-name' ) );
return;
}
this.moveReason = jQuery( '#mtsg-reason' ).val().trim();
this.moveMessage = jQuery( '#mtsg-message' ).val().trim();
if ( this.moveMessage == jQuery.trim( mw.message( 'mtsg-default-message' ).plain() ) ) {
alert( mw.msg( 'mtsg-error-move-message-not-changed' ) );
//nie działa, zob. linie od 170
return;
}
if ( this.moveMessage.match(/\* \.\.\./) ) {
alert( mw.msg( 'mtsg-error-move-message-not-changed-reasons' ) );
return;
}
var buttons = jQuery( dialog ).dialog( 'option', 'buttons' );
delete buttons[mw.msg( 'mtsg-confirm-button' )];
jQuery( dialog ).dialog( 'option', 'buttons', buttons );
var moved_article_id = mw.config.get( 'wgArticleId' );
this.jobQueue = [];
this.jobQueue.push( {
name: 'move',
description: mw.msg( 'mtsg-move-page-job' ),
execute: function() {
var job = this;
var request = {
action: 'move',
fromid: moved_article_id,
to: gadget.moveDestination,
reason: gadget.moveReason,
movetalk: 1
}
if ( gadget.canSuppressRedirect ) {
request['noredirect'] = 1;
}
gadget.callApi( request, function( data ) {
if ( data.error && data.error.code ) {
gadget.showError( data.error.code );
} else {
job.callback();
}
} );
}
} );
if ( !gadget.canSuppressRedirect ) {
this.jobQueue.push( {
name: 'speedy',
description: mw.msg( 'mtsg-insert-speedy-job' ),
execute: function() {
var job = this;
var request = {
action: 'edit',
title: gadget.moveSource,
prependtext: mw.message( 'mtsg-speedy-template', gadget.moveDestination ).plain(),
nocreate: 1,
summary: mw.msg( 'mtsg-speedy-summary' )
}
gadget.editPage( request, function( data ) {
if ( !data.edit || data.edit.result != 'Success' ) {
gadget.showError( mw.msg( 'mtsg-error-api-error' ) );
} else {
job.callback();
}
} );
}
} );
}
this.jobQueue.push( {
name: 'block-categorization',
description: mw.msg( 'mtsg-edit-article' ),
execute: function() {
var job = this;
var request = {
action: 'query',
prop: 'revisions',
rvprop: 'content',
rvdir: 'older',
titles: gadget.moveDestination,
rvlimit: 1,
rvslots: 'main',
};
gadget.callApi(request, function (data) {
var content = data.query.pages[moved_article_id].revisions[0].slots.main['*'];
// article content cleanup
var editWikiTextSummary = [];
var contentChanged = false;
if (content.search(/\[\[kategoria:/i) >= 0) {
contentChanged = true;
content = content.replace(/\[\[kategoria:/gi, '[[:Kategoria:');
editWikiTextSummary.push(mw.msg('mtsg-block-categorization-summary'));
}
if (content.search(/\{\{ek\s*[|}]/i) >= 0) {
contentChanged = true;
content = content.replace(/\{\{ek[^}]*\}\}\s*/gi, '');
editWikiTextSummary.push(mw.msg('mtsg-remove-tpl-summary').replace(/%tpl%/g, 'EK'));
}
if (content.search(/\{\{dnu\s*[|}]/i) >= 0) {
contentChanged = true;
content = content.replace(/\{\{dnu[^}]*\}\}\s*/gi, '');
editWikiTextSummary.push(mw.msg('mtsg-remove-tpl-summary').replace(/%tpl%/g, 'DNU'));
}
// update article if auto-cleanup was required
if(contentChanged) {
var request = {
action: 'edit',
title: gadget.moveDestination,
text: content,
nocreate: true,
minor: true,
summary: editWikiTextSummary.join(', ')
}
gadget.editPage( request, function( data ) {
if ( !data.edit || data.edit.result != 'Success' ) {
gadget.showError( mw.msg( 'mtsg-error-api-error' ) );
} else {
job.callback();
}
} );
} else {
job.callback();
}
});
}
} );
if ( this.moveMessage != '' ) {
this.jobQueue.push( {
name: 'message',
description: mw.msg( 'mtsg-send-message-job' ),
messageTitle: '[[:' + this.moveSource + '|' + this.moveSource + ']]',
messageText: this.moveMessage.replace( /\$link/g, this.moveDestination ),
execute: function() {
var job = this;
var message = this.messageText;
var subject = this.messageTitle;
mw.loader.using(['mediawiki.Title', 'mediawiki.messagePoster'], function () {
var title = new mw.Title('User talk:' + gadget.author);
mw.messagePoster.factory.create(title).done(function (poster){
poster.post(subject, message).done(function(data){
if ( (!data.edit || data.edit.result != 'Success') && (!data.flow || data.flow['new-topic'].status != 'ok') ) {
gadget.showError( mw.msg( 'mtsg-error-api-error' ) );
} else {
job.callback();
}
});
} );
} );
}
} );
}
this.jobQueue.push( {
name: 'redirect',
description: mw.msg( 'mtsg-redirect-job' ),
execute: function() {
setTimeout( function() {
window.location = mw.util.getUrl( gadget.moveDestination );
}, 1000 );
}
} );
gadget.processQueue();
},
/**
* Performs MediaWiki call using post method.
* @param request
* Api request.
* @param callback
* Function to be called when request is completed.
*/
callApi: function( request, callback ) {
var gadget = this;
if ( gadget.debug ) {
console.log( 'Sending api request: ', request );
}
request.format = 'json';
var ondone = function( data ) {
if ( gadget.debug ) {
console.log( 'Response: ', data );
}
try {
callback( data );
} catch ( e ) {
gadget.handleException( e );
}
};
var onfail = function (a, b) {
ondone(b);
console.log('failed: ', b, ', a is:', a);
}
if(request.action == "query") gadget.api.get(request).done(ondone).fail(onfail); else gadget.api.postWithEditToken(request).done(ondone).fail(onfail);
},
/**
* Performs edit, fetches edit token if not provided.
* @param request
* Api request.
* @param callback
* Function to be called when request is completed.
*/
editPage: function( request, callback ) {
var gadget = this;
if ( request.title == null ) {
throw new Error( 'Page title is missing' );
}
if ( callback == null ) {
throw new Error( 'Callback is missing' );
}
gadget.callApi( request, callback );
}
};
moveToSandboxGadget.init();
Text is available under the CC BY-SA 4.0 license; additional terms may apply.
Images, videos and audio are available under their respective licenses.