MediaWiki:Gadget-cambusa.js: differenze tra le versioni

Da Semi del Verbo, l'enciclopedia dell'influenza del Vangelo sulla cultura
m (mw.util.addCSS)
 
m (una versione importata)
 
(Nessuna differenza)

Versione attuale delle 22:40, 30 ago 2020

/**
 * Gadget-cambusa.js
 * Aggiunge il link "cambusa" a ogni discussione della pagina, per effettuare
 * lo spostamento della discussione, usando i template cambusa e cambusada.
 *
 * @author https://it.wikipedia.org/wiki/Utente:Rotpunkt
 */
/* global mediaWiki, jQuery, OO */

( function ( mw, $ ) {
	'use strict';

	// Le pagine di partenza e destinazione per la cambusa
	// possono appartenere solo ai namespace di discussione,
	// più le pagine qui di seguito configurate:
	var extraPages = {
			4: [ 'Officina', 'Oracolo' ],
			12: [ 'Sportello informazioni' ]
	};
	// Per verificare se i link "Cambusa" sono già stati aggiunti
	var inited = false;
	// mw.Api utilizzata durante lo spostamento della discussione
	var api;
	// La finestra di dialogo per configurare lo spostamento della discussione
	var cambusaDialog;

	/**
	 * Ottiene il contenuto di una sezione della pagina corrente.
	 *
	 * @param {string} section - La sezione da leggere
	 * @param {function} readHandler - La funzione da richiamare con il risultato
	 */
	function getSection( section, readHandler ) {
		api.get( {
			action: 'query',
			format: 'json',
			prop: 'revisions',
			titles: mw.config.get( 'wgPageName' ),
			rvprop: 'content',
			rvsection: section,
		} ).done ( function ( data ) {
			var text = data.query.pages[ Object.keys( data.query.pages )[ 0 ] ].revisions[ 0 ][ '*' ];
			readHandler( text );
		} ).fail ( function ( code, data ) {
			OO.ui.getWindowManager().getCurrentWindow().close();
			OO.ui.alert( 'Errore nel leggere la discussione: ' + code );
		} );
	}

	/**
	 * Modifica una sezione della pagina corrente.
	 *
	 * @param {string} section - La sezione da modificare
	 * @param {string} text - Il nuovo contenuto
	 * @param {string} summary - L'oggetto della modifica
	 */
	function setSection( section, text, summary ) {
		api.postWithEditToken( {
			action: 'edit',
			format: 'json',
			title: mw.config.get( 'wgPageName' ),
			section: section,
			text: text,
			summary: summary
		} ).done ( function ( data ) {
			location.reload();
		} ).fail ( function ( code, data ) {
			OO.ui.getWindowManager().getCurrentWindow().close();
			OO.ui.alert( 'Errore nel modificare la discussione: ' + code );
		} );
	}

	/**
	 * Aggiunge una sezione a una pagina.
	 *
	 * @param {string} title - Il nome della pagina
	 * @param {string} sectiontitle - Il titolo della nuova sezione
	 * @param {string} text - Il contenuto della nuova sezione
	 * @param {function} successHandler - La funzione da richiamare in caso di successo
	 */
	function addSection( title, sectiontitle, text, successHandler ) {
		api.newSection( title, sectiontitle, text )
			.done( function ( data ) {
				successHandler( data.edit.newrevid );
			} )
			.fail ( function ( code, data ) {
				OO.ui.getWindowManager().getCurrentWindow().close();
				OO.ui.alert( 'Errore nel creare la discussione: ' + code );
			} );
	}

	/**
	 * Ottiene l'anchor dell'ultima discussione di una data versione di una pagina.
	 *
	 * @param {string} oldid - L'id della versione della pagina
	 * @param {function} anchorHandler - La funzione da richiamare con il risultato
	 */
	function getSectionAnchor( oldid, anchorHandler ) {
		api.get( {
			action: 'parse',
			format: 'json',
			oldid: oldid,
			prop: 'sections',
		} ).done ( function ( data ) {
			anchorHandler( data.parse.sections[ data.parse.sections.length - 1 ].anchor );
		} ).fail ( function ( code, data ) {
			OO.ui.getWindowManager().getCurrentWindow().close();
			OO.ui.alert( 'Errore nel leggere l\'anchor della sezione: ' + code );
		} );
	}

	/**
	 * Gestore del click sul pulsante "Cambusa" della finestra di dialogo.
	 */
	function cambusaHandler() {
		var from, text, error, formData = cambusaDialog.getFormData();

		if ( !formData.destTitle ) {
			error = 'Il campo pagina è obbligatorio.';
		} else if ( ( formData.destNamespace + ':' + formData.destTitle ).replace( / /g, '_' ) === mw.config.get( 'wgPageName' ) ) {
			error = 'La pagina di destinazione deve essere diversa dalla corrente.';
		} else if ( !formData.destSectionTitle ) {
			error = 'Il campo titolo è obbligatorio.';
		} else if ( extraPages[ formData.destNamespaceNum ] &&
					$.inArray( formData.destTitle, extraPages[ formData.destNamespaceNum ] ) === -1 ) {
			error = 'Le pagine valide nel namespace ' + formData.destNamespace + ' sono: ' +
					extraPages[ formData.destNamespaceNum ].join( ', ' );
		}

		if ( error ) {
			OO.ui.alert( error );
		} else {
			cambusaDialog.close();
			formData.destTitle = formData.destNamespace + ':' + formData.destTitle;
			from = mw.config.get( 'wgPageName' ).replace( /_/g, ' ' );
			text = '{{Cambusada|' + from + '|firma=~~\~~}}\n' + formData.sourceText;
			// @todo L'utilizzo dell'alert qui rende necessaria una chiamata a OO.ui.getWindowManager().getCurrentWindow().close()
			// prima di poter mostrare ulteriori alert
			OO.ui.alert( 'Spostamento in corso...' );
			addSection( formData.destTitle, formData.destSectionTitle, text, function ( newrevid ) {
				getSectionAnchor( newrevid, function ( anchor ) {
					text = '==' + formData.destSectionTitle + '==\n\n' +
						'{{Cambusa|' + formData.destIncipit + '|' + formData.destTitle + '#' + anchor + '|firma=~~\~~}}';
					setSection( formData.sourceSection, text, 'cambusata discussione in [[' + formData.destTitle + ']]' );
				} );
			} );
		}
	}

	/**
	 * Crea la finestra di dialogo per configurare lo spostamento della discussione.
	 * 
	 * @return {Object} L'oggetto derivato da OO.ui.Dialog che rappresenta la finestra
	 */
	function buildCambusaDialog() {
		var style = '.gc-container-button { width: 100%; text-align: center; margin-top: 10px }';
		mw.util.addCSS( style );
		function CambusaDialog( config ) {
			CambusaDialog.parent.call( this, config );
		}
		OO.inheritClass( CambusaDialog, OO.ui.Dialog );
		CambusaDialog.static.name = 'cambusaDialog';
		CambusaDialog.prototype.initialize = function () {
			var self = this;
			CambusaDialog.parent.prototype.initialize.call( this );
			// scelta namespace
			var ns = [];
			$.each( mw.config.get( 'wgFormattedNamespaces' ), function ( key, value ) {
				key = parseInt( key );
				if ( key > 0 && ( key % 2 === 1 || extraPages[ key ] ) ) {
					ns.push( new OO.ui.MenuOptionWidget( { data: key, label: value } ) );
				}
			} );
			this.namespaceDropdown = new OO.ui.DropdownWidget( {
				menu: { items: ns }
			} );
			this.namespaceDropdown.getMenu().on( 'select', function () {
				var ns = self.namespaceDropdown.getMenu().findSelectedItem().getData();
				self.destInput.setNamespace( ns );
			} );
			// pagina di destinazione
			this.destInput = new mw.widgets.TitleInputWidget( {
				validateTitle: true
			} );
			// titolo sezione
			this.sectionTitleInput = new OO.ui.TextInputWidget();
			// incipit
			this.incipitInput = new OO.ui.TextInputWidget();
			var cambusaButton = new OO.ui.ButtonWidget( {
				label: 'Cambusa',
			} ).on( 'click', cambusaHandler );
			var cancelButton = new OO.ui.ButtonWidget( {
				label: 'Annulla'
			} ).on( 'click', function () {
				self.close();
			} );
			// FieldsetLayout
			var fieldsetLayout = new OO.ui.FieldsetLayout( {
				items: [
					new OO.ui.FieldLayout( this.namespaceDropdown, {
						label: 'Namespace destinazione:',
						align: 'top'
					} ),
					new OO.ui.FieldLayout( this.destInput, {
						label: 'Pagina destinazione (senza namespace):',
						align: 'top'
					} ),
					new OO.ui.FieldLayout( this.sectionTitleInput, {
						label: 'Titolo nuova discussione:',
						align: 'top'
					} ),
					new OO.ui.FieldLayout( this.incipitInput, {
						label: 'Incipit (facoltativo):',
						align: 'top'
					} ),
					new OO.ui.HorizontalLayout( {
						items: [ cambusaButton, cancelButton ],
						classes: [ 'gc-container-button' ]
					} )
				]
			} );
			this.panelLayout = new OO.ui.PanelLayout( { padded: true, expanded: false } );
			this.panelLayout.$element.append( fieldsetLayout.$element );
			this.$body.append( this.panelLayout.$element );
		};
		CambusaDialog.prototype.getBodyHeight = function () {
			return this.panelLayout.$element.outerHeight( true );
		};
		CambusaDialog.prototype.setSourceSection = function ( sourceSection, sourceSectionTitle, sourceText ) {
			this.sourceSection = sourceSection;
			this.sectionTitleInput.setValue( sourceSectionTitle );
			this.sourceText = sourceText;
			this.destInput.setValue( '' );
			this.namespaceDropdown.getMenu().selectItemByData( 1 );
		};
		CambusaDialog.prototype.getFormData = function () {
			return {
				destTitle: $.trim( this.destInput.getValue() ),
				destSectionTitle: $.trim( this.sectionTitleInput.getValue() ),
				destIncipit: $.trim( this.incipitInput.getValue() ),
				destNamespace: this.namespaceDropdown.getMenu().findSelectedItem().getLabel(),
				destNamespaceNum: this.namespaceDropdown.getMenu().findSelectedItem().getData(),
				sourceSection: this.sourceSection,
				sourceText: this.sourceText
			};
		};
		return new CambusaDialog( {
			size: 'small'
		} );
	}

	/**
	 * Aggiunge il link "Cambusa" a ogni sezione della pagina corrente.
	 */
	function addCambusaLinks() {
		var windowManager;
		$( 'span.mw-editsection > a:last-of-type' ).each( function ( i, el ) {
			var $link, sectiontitle = $( el ).attr( 'title' ).replace( /^(Modifica|Cancella) la sezione /g, '' );
			$link = $( '<a>' )
				.attr( 'href', '#' )
				.attr( 'title', 'Cambusa la discussione ' + sectiontitle )
				.text( 'cambusa' )
				.click( function ( event ) {
					event.preventDefault();
					mw.loader.using( [ 'mediawiki.api', 'oojs-ui-core', 'oojs-ui-widgets',
						'oojs-ui-windows', 'mediawiki.widgets' ]
					)
						.done( function () {
							api = new mw.Api();
							getSection( i + 1, function ( text ) {
								var match = text.match( /==\s*(.*?)\s*==\s*\n([\s\S]*)/ );
								if ( !cambusaDialog ) {
									cambusaDialog = buildCambusaDialog();
									windowManager = new OO.ui.WindowManager();
									$( 'body' ).append( windowManager.$element );
									windowManager.addWindows( [ cambusaDialog ] );
								}
								cambusaDialog.setSourceSection( i + 1, match[ 1 ], match[ 2 ] );
								windowManager.openWindow( cambusaDialog );
							} );
						} )
						.fail( function () {
							console.error( 'Impossibile avviare l\'accessorio cambusa.' );
						} );
				} );
			$( el ).after( '<span> | </span>', $link );
		} );
	}

	/**
	 * Restituisce true se la pagina corrente può utilizzare il link "cambusa".
	 *
	 * @return {boolean}
	 */
	function cambusaLinksAllowed() {
		var ns = mw.config.get( 'wgNamespaceNumber' ),
			title = mw.config.get( 'wgTitle' );
		return ns % 2 === 1 ||
			( extraPages[ ns ] && $.inArray( title, extraPages[ ns ] ) !== -1 );
	}

	$( function () {
		if ( mw.config.get( 'wgAction' ) === 'view' && cambusaLinksAllowed() ) {
			var portletLink = mw.util.addPortletLink( 'p-tb', '#', 'Cambusa', 't-cambusa', 'Aggiunge il link cambusa a ogni discussione' );
			$( portletLink ).click( function ( event ) {
				event.preventDefault();
				if ( !inited ) {
					addCambusaLinks();
					inited = true;
				}
			} );
		}
	} );
}( mediaWiki, jQuery ) );