User:XXN/Gadget-Move.js

From Wikidata
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * Adds a move tool to the sitelink edit toolbar to move a sitelink to another item.
 */

( function ( mw, wb, $ ) {

	if ( mw.config.get( 'wgNamespaceNumber' ) !== 0 ||
		!mw.config.exists( 'wbEntity' )
	) {
		return;
	}

	switch ( mw.config.get( 'wgUserLanguage' ) ) {
	default:
	case 'en':
		mw.messages.set( {
			'move': 'Move',
			'move-toolbar': 'move',
			'close': 'Close',
			'newitem': 'The id of the new item',
			'intro': 'You can move a sitelink to another item. Please give a valid item id and check if the link for the new item is already set. Also remember to move label and descriptions.',
			'success': 'The sitelink $2 was successfully moved to $1.',
			'success-multi': 'The sitelinks $2 were sucessfully moved to $1.',
			'error-sameid': 'The new item\'s id has to be different to the current one\'s.',
			'error-invalidid': 'The given id is not a valid item identifier.',
			'error-notexisting': 'The item with the id $1 does not exist.',
			'error-overwrite': 'The link for the given site in $1 is already set. Please check the item\'s id or remove the link from the item.',
			'error-api': 'There was an error editing the item: $1'
		} );
		break;
	}

	var api = new mw.Api(),
		repoApi = new wb.api.RepoApi( api ),
		olditem = mw.config.get( 'wbEntityId' ), // current item
		sitelinks = JSON.parse( mw.config.get( 'wbEntity' ) ).sitelinks, // current sitelinks
		sites, // ids of the sites to move
		newitem, // target item
		baseRevId = mw.config.get( 'wgCurRevisionId' ), // current revision id
		baseRevIdTarget; //  current revision id of the target item

	function createSpinner() {
		$( '#move-result' ).html(
			$.createSpinner( {
				size: 'large',
				type: 'block'
			} )
		);
	}

	function showError( error ) {
		var parameters = Array.prototype.slice.call( arguments, 1 );
		$( '#move-result' ).html(
			$( '<p>' )
			.attr( 'class', 'error' )
			.html( mw.message( 'error-' + error ).params( parameters ).parse() )
		);
	}

	function onError( error, result ) {
		showError( 'api', result && result.error && result.error.info || error );
	}

	function success() {
		var message = mw.message(
			sites.length > 1 ? 'success-multi' : 'success',
			mw.html.element( 'a', { href: mw.util.getUrl( newitem ) }, newitem ),
			''
		);

		$( '#move' ).dialog( 'close' );

		// Hide moved sitelinks
		$( $.map( sites, function ( site ) {
			return $( '.wikibase-sitelinkview-' + site ).get( 0 );
		} ) ).hide( 400 );

		// Todo: Remove site from wikibase store to allow readding this sitelink.
		mw.notify( message, {
			autoHide: false,
			title: mw.msg( 'move' )
		} );
	}

	function move() {
		var newData, oldData, i, sitelink;

		if ( sites.length > 1 ) {
			newData = { sitelinks: {} };
			oldData = { sitelinks: {} };
	
			for ( i in sites ) {
				newData.sitelinks[sites[i]] = sitelinks[sites[i]];
				oldData.sitelinks[sites[i]] = { site: sites[i], remove: true };
			}

			api.postWithEditToken( {
				formatversion: 2,
				action: 'wbeditentity',
				id: olditem,
				baserevid: baseRevId,
				data: JSON.stringify( oldData ),
				summary: 'Moving sitelinks to [[' + newitem + ']]'
			} )
			.fail( onError )
			.done( function () {
				api.postWithEditToken( {
					formatversion: 2,
					action: 'wbeditentity',
					id: newitem,
					baserevid: baseRevIdTarget,
					data: JSON.stringify( newData ),
					summary: 'Moving sitelinks from [[' + olditem + ']]'
				} )
				.fail( onError )
				.done( success );
			} );
		} else {
			sitelink = sitelinks[sites[0]];

			api.postWithEditToken( {
				formatversion: 2,
				action: 'wbsetsitelink',
				id: olditem,
				baserevid: baseRevId,
				linksite: sitelink.site,
				summary: 'Moving sitelink to [[' + newitem + ']]'
			} )
			.fail( onError )
			.done( function () {
				api.postWithEditToken( {
					formatversion: 2,
					action: 'wbsetsitelink',
					id: newitem,
					baserevid: baseRevIdTarget,
					linksite: sitelink.site,
					linktitle: sitelink.title,
					badges: sitelink.badges.join( '|' ),
					summary: 'Moving sitelink from [[' + olditem + ']]'
				} )
				.fail( onError )
				.done( success );
			} );
		}
	}

	function performMove() {
		createSpinner();
		newitem = $( '#move-newitem' ).val().toUpperCase().match(/Q\d+/g)[0];
		if ( olditem === newitem ) {
			showError( 'sameid' );
			return;
		}
		if ( newitem.match( /Q\d+/g ) === null ) {
			showError( 'invalidid' );
			return;
		}
		repoApi.getEntities( newitem, ['info', 'sitelinks'] )
		.fail( onError )
		.done( function ( data ) {
			if ( !data.entities.hasOwnProperty( newitem ) ) {
				showError( 'notexisting', mw.html.element( 'a', { href: mw.util.getUrl( newitem ) }, newitem ) );
				return;
			}

			var entity = data.entities[newitem];

			if ( entity.hasOwnProperty( 'redirects' ) ) {
				newitem = entity.redirects.to;
			}

			for ( var i in sites ) {
				if ( entity.sitelinks && entity.sitelinks[sites[i]] ) {
					showError( 'overwrite', mw.html.element( 'a', { href: mw.util.getUrl( newitem ) }, newitem ) );
					return;
				}
			}

			baseRevIdTarget = entity.lastrevid;

			move();
		} );
	}

	function openDialog() {
		$( '#move-result' ).empty();
		$( '#move' ).dialog( 'open' );
	}

	function init() {
		// Add click listener
		$( '.wikibase-sitelinkview' ).each( function () {
			var site = $( this ).data( 'wbSiteid' );
			$( this )
			.prepend(
				$( '<a>' )
				.attr( {
					'class': 'move-button',
					'href': '#',
					'title': mw.msg( 'move-toolbar' )
				} )
				.click( function ( event ) {
					event.preventDefault();
					sites = [ site ];
					openDialog();
				} )
			);
		} );

		$( '.wikibase-sitelinkgroupview' ).each( function () {
			var $this = $( this );
			if ( $this.find( '.wikibase-sitelinkview.listview-item' ).length > 0 ) {
				$this.find('.wikibase-edittoolbar-container').append(
					$( '<span>' )
					.attr( 'class', 'move-group' )
					.append(
						'[',
						$( '<a>' )
						.attr( 'href', '#' )
						.text( mw.msg( 'move-toolbar' ) )
						.click( function ( event ) {
							event.preventDefault();
							sites = $this.find( '.wikibase-sitelinkview.listview-item' ).map( function () {
								return $( this ).data( 'wb-siteid' );
							} ).get();
							openDialog();
						} ),
						']'
					)
				);
			}
		} );

		// Create dialog
		$( '<div>' )
		.attr( 'id', 'move' )
		.append(
			$( '<form>' )
			.submit( function ( event ) {
				event.preventDefault();
				performMove();
			} )
			.append(
				$( '<fieldset>' )
				.attr( 'id', 'sitelink-form' )
				.append(
					$( '<legend>' )
					.text( mw.msg( 'move' ) ),
					// </legend>
					$( '<p>' )
					.attr( 'id', 'sitelink-intro' )
					.text( mw.msg( 'intro' ) ),
					// </p>
					$( '<p>' )
					.append(
						$( '<label>' )
						.attr( {
							'for': 'move-newitem',
							'class': 'move-label'
						} )
						.text( mw.msg( 'newitem' ) + ': ' ),
						// </label>
						$( '<input>' )
						.attr( {
							'type': 'text',
							'id': 'move-newitem',
							'class': 'move-input'
						} )
					)
				) // </p>
			), // </fieldset>
			// </form>
			$( '<p>' )
			.attr( 'id', 'move-result' )
		)
		.dialog( {
			dialogClass: 'move-dialog',
			title: mw.message( 'move' ).escaped(),
			autoOpen: false,
			modal: true,
			width: 500,
			buttons: [ {
				id: 'move-button-move',
				text: mw.msg( 'move' ),
				click: function ( event ) {
					event.preventDefault();
					performMove();
				}
			}, {
				id: 'move-button-close',
				text: mw.msg( 'close' ),
				click: function ( event ) {
					event.preventDefault();
					$( '#move' ).dialog( 'close' );
				}
			} ]
		} );
	}

	$( init );
} ( mediaWiki, wikibase, jQuery ) );