Lista haseł | Kategorie artykułów | Prześlij plik | Lista plików | Pomoc | Kontakt
Pnikut.net
Aby utworzyć nowe konto użytkownika należy postępować zgodnie z zaleceniami na stronie Tworzenie konta użytkownika.

MediaWiki:Gadget-move-to-sandbox.js

Z Wiki.Pnikuczanie
Skocz do: nawigacji, wyszukiwania

Uwaga: aby zobaczyć zmiany po zapisaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.

  • Firefox / Safari: Przytrzymaj Shift podczas klikania Odśwież bieżącą stronę, lub naciśnij klawisze Ctrl+F5 lub Ctrl+R (⌘-R na komputerze Mac)
  • Google Chrome: Naciśnij Ctrl-Shift-R (⌘-Shift-R na komputerze Mac)
  • Internet Explorer: Przytrzymaj Ctrl jednocześnie klikając Odśwież lub naciśnij klawisze Ctrl+F5
  • Opera: Wyczyść pamięć podręczną w Narzędzia → Preferencje
/* Translatable strings */
mw.messages.set( {
	'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-link-placeholder': '$link',
	'mtsg-default-message': 'Witaj. Twój artykuł nie nadaje się jeszcze do publikacji w Wikipedii, dlatego został przeniesiony do twojego brudnopisu [[$link]], gdzie możesz nad nim popracować. Należy w nim poprawić:\n* ...\n* ...\n* ...\nPo skończeniu użyj [[Pomoc:Zmiana nazwy strony|zakładki przenieś]], aby opublikować go ponownie. Jeżeli nie możesz przenieść samodzielnie (należy mieć konto zarejestrowane od co najmniej 4 dni oraz 10 edycji), zwróć się do dowolnego bardziej zaawansowanego wikipedysty lub do [[WP:PdA|administratorów]]. Pozdrawiam, ~~' + '~~',
	'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-error-nonexistent-page': 'Artykuł nie istnieje.',
	'mtsg-error-unknown-author': 'Nie można określić autora artykułu.',
	'mtsg-error-anonymous-author': 'Anonimowy użytkownik nie posiada brudnopisu.',
	'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-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' // FIXME
} );

window.moveToSandboxGadget = { /** Version of the gadget */
	version: 7,

	/* Gadget variables */
	canSuppressRedirect: false,
	moveToken: null,
	moveSource: mw.config.get( 'wgPageName' ).replace( /_/g, ' ' ),
	moveDestination: null,
	moveReason: null,
	author: null,
	jobQueue: [],
	currentJob: null,
	debug: false,

	/** 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">' + mw.message( 'mtsg-default-message' ).plain() + '</textarea>' +
			'</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,
			intoken: 'move'
		};

		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.wikiGetlink('User:' + revision.user)).append(document.createTextNode(revision.user)),
				' (',
				jQuery('<a>' + mw.msg( 'mtsg-user-talk-link' ) + '</a>').attr('href', mw.util.wikiGetlink('User_talk:' + revision.user)),
				', ',
				jQuery('<a>' + mw.msg( 'mtsg-user-contribs-link' ) + '</a>').attr('href', mw.util.wikiGetlink('Special:Contributions/' + revision.user)),
				')'
			);

			if ( !revision.userid ) {
				that.showError( mw.msg( 'mtsg-error-anonymous-author' ) );
				return;
			}

			jQuery( '#mtsg-destination' ).attr( 'disabled', false ).val( mw.config.get( 'wgFormattedNamespaces' )[2] + ':' + revision.user + '/' + 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.moveToken = page.movetoken;
			that.author = revision.user;

			// Add confirm button
			buttons[mw.msg( 'mtsg-confirm-button' )] = function() {
				that.confirm( dialog )
			};
			jQuery( dialog ).dialog( "option", "buttons", buttons );
		} );
	},

	/** 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/3/34/Crystal_Clear_app_clean.png/16px-Crystal_Clear_app_clean.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/9/99/Crystal_128_error.svg/16px-Crystal_128_error.svg.png';
		}
	},

	/** Exception handler */
	handleException: function( e ) {
		var message = errorCaughtException + '\n' + e.name + ':' + e.message;
		if ( e.stack ) {
			message += '\n' + e.stack;
		}
		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( success ) {
			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.msg( 'mtsg-default-message' ) ) ) {
			alert( mw.msg( 'mtsg-error-move-message-not-changed' ) );
			return;
		}

		var buttons = jQuery( dialog ).dialog( 'option', 'buttons' );
		delete buttons[mw.msg( 'mtsg-confirm-button' )];
		jQuery( dialog ).dialog( 'option', 'buttons', buttons );

		this.jobQueue = [];
		this.jobQueue.push( {
			name: 'move',
			description: mw.msg( 'mtsg-move-page-job' ),
			execute: function() {
				var job = this;

				var request = {
					action: 'move',
					fromid: mw.config.get( 'wgArticleId' ),
					to: gadget.moveDestination,
					token: gadget.moveToken,
					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();
						}
					} );
				}
			} );
		}

		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 request = {
						action: 'edit',
						title: 'User talk:' + gadget.author,
						text: this.messageText,
						section: 'new',
						summary: this.messageTitle
					}

					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: 'redirect',
			description: mw.msg( 'mtsg-redirect-job' ),
			execute: function() {
				setTimeout( function() {
					window.location = mw.util.wikiGetlink( 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';
		jQuery.post( mw.util.wikiScript( 'api' ), request, function( data ) {
			if ( gadget.debug ) {
				console.log( 'Response: ', data );
			}
			try {
				callback( data );
			} catch ( e ) {
				gadget.handleException( e );
			}
		}, 'json' );
	},
	/**
	 * 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' );
		}

		if ( request.token == null ) {
			var tokenRequest = {
				action: 'query',
				prop: 'info',
				format: 'json',
				titles: request.title,
				intoken: 'edit'
			}
			gadget.callApi( tokenRequest, function( data ) {
				if ( data.error ) {
					callback( data );
					return;
				}
				var page;
				for ( var pageId in data.query.pages ) {
					page = data.query.pages[pageId];
				}
				if ( !page || page.edittoken == null ) {
					callback( data );
					return;
				}
				request.title = page.title;
				request.token = page.edittoken;
				gadget.editPage( request, callback );
			} );
		} else {
			gadget.callApi( request, callback );
		}
	}
};

moveToSandboxGadget.init();