User:Ash Crow/skating-competitions-creation-helper.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.
/*
* SkatingCompetitionsCreationHelper
*
* Allow the user to easily add new items for skating competitions.
*
* Scope Statement: https://notes.wikimedia.fr/p/patinage
* Author: [[User:Ash_Crow]]
*/
//<nowiki>


// Target page: https://www.wikidata.org/wiki/User:Ash_Crow/creation-helpers
if ( mw.config.get( 'wgArticleId' ) === 58375215 ) {
  mw.loader.using( [ 'oojs-ui', 'mediawiki.util', 'mediawiki.widgets', 'mediawiki.widgets.datetime', 'mediawiki.api' ], function() {

    /*
	** Localization
	*/
    var messages = {
      'en': {
        'link-title': 'Add competition parts',
        'box-title': 'Add competition parts',
        'action-cancel': 'Cancel',
        'action-save': 'Create',
        'canceled': 'Action canceled',
        'notif-done':  'Action done on item $1.',
        'notif-fail': 'Action failed on item $1.',
        'no-data': 'The form is empty!',
        'comp_qid-label': 'Qid of the competition',
        'warning-message': 'This will create three items, please make sure that they do not already exist.',
        'discipline-label': 'Discipline',
        'men-single-label': 'men\'s singles figure skating',
        'ladies-single-label': 'women\'s singles figure skating',
        'pairs-label': 'pair skating',
        'dancing-label': 'ice dancing (since July 2018 only)',
        'dancing-2010-label': 'ice dancing (2010-2018)',
        'dancing-1967-label': 'ice dancing (1967-2010)',
        'dateshort-label': 'Date of the short program',
        'dateshort-help': 'If ice dancing, equivalent to compulsory dance (1967-2010), short dance (2010-2018), or rhythm dance (2018-)',
        'datefree-label': 'Date of the free program',
        'datethird-label': 'Date of the original dance program',
        'datethird-help': 'Only for ice dancing (1967-2010)',
        'link-label': 'Reference URL',
        'new-item': 'New item created: ',
        'item-creation-fail: ': 'Item creation failed',
        'missing-mandatory': 'Missing mandatory claim in the competition item: ',
        'comp-data-fail': 'Impossible to retrieve the claims on the competition item'
      },
      'fr': {
        'link-title': 'Ajouter les parties de la compétition',
        'box-title': 'Ajouter les parties de la compétition',
        'action-cancel': 'Annuler',
        'action-save': 'Créer',
        'canceled': 'Action annulée',
        'notif-done':  'Action effectuée sur l’élément $1.',
        'notif-fail': 'Échec de l’action sur l’élément $1.',
        'no-data': 'Le formulaire est vide !',
        'comp_qid-label': 'Qid de la compétition',
        'warning-message': 'Cela va créer trois éléments, merci de vérifier qu’ils n’existent pas déjà.',
        'discipline-label': 'Discipline',
        'men-single-label': 'patinage individuel messieurs',
        'ladies-single-label': 'patinage individuel dames',
        'pairs-label': 'patinage en couple',
        'dancing-label': 'danse sur glace (depuis juillet 2018 uniquement)',
        'dancing-2010-label': 'danse sur glace (2010-2018)',
        'dancing-1967-label': 'danse sur glace (1967-2010)',
        'dateshort-label': 'Date du programme court',
        'dateshort-help': 'Pour la danse sur glace, correspond à danse imposée (1967-2010), danse courte (2010-2018), ou danse rythmique (2018-)',
        'datefree-label': 'Date du programme libre',
        'datethird-label': 'Date du programme de danse originale',
        'datethird-help': 'Seulement pour la danse sur glace (1967-2010)',
        'link-label': 'URL de la référence',
        'new-item': 'Nouvel élément créé : ',
        'item-creation-fail': 'Échec de la création de l’élément: ',
        'missing-mandatory': 'Déclaration obligatoire manquante sur l’élément de la compétition : ',
        'comp-data-fail': 'Impossible de récupérer les déclarations sur l’élément de la compétition.'
      },
    };

    mw.messages.set( messages[ 'en' ] );
    var lang = mw.config.get( 'wgUserLanguage' );
    if ( lang && lang != 'en' && lang in messages ) {
    	mw.messages.set( messages[ lang ] );
    }

    // Button
    $( '#creationhelper-button').text(mw.msg('box-title'));
    $( '#creationhelper-button' ).on( 'click', function ( e ) {
    	windowManager.openWindow( processDialog );
    	e.preventDefault();
    } );

    // Subclass ProcessDialog.
    function ProcessDialog( config ) {
    	ProcessDialog.super.call( this, config );
    }
    OO.inheritClass( ProcessDialog, OO.ui.ProcessDialog );

    // Specify a name for .addWindows()
    ProcessDialog.static.name = 'creationHelperDialog';
    // Specify a static title and actions.
    ProcessDialog.static.title = mw.msg('box-title');
    ProcessDialog.static.size = 'larger';
	ProcessDialog.static.height = 600;
    ProcessDialog.static.actions = [
    	{ action: 'save',
    	  label: mw.msg('action-save'),
    	  flags: [ 'primary', 'progressive'] },
    	{ label: mw.msg('action-cancel'), flags: 'safe' }
    ];
    
    // Use the initialize() method to add content to the dialog's $body, 
    // to initialize widgets, and to set up event handlers. 
    ProcessDialog.prototype.initialize = function () {
    	ProcessDialog.super.prototype.initialize.apply( this, arguments );
    	
    	var self = this;
    	var MainPageLayout = function( name, config ) {
    		MainPageLayout.super.call( this, name, config );
    		this.comp_qid = new WikidataSearchWidget( { required: true } );
	    	this.discipline = new OO.ui.DropdownWidget( {
	    		required: true, 
				label: mw.msg('discipline-label'),
				menu: {
					items: [
						new OO.ui.MenuOptionWidget( {
							data: 'men-single',
							label: mw.msg('men-single-label'),
						} ),
						new OO.ui.MenuOptionWidget( {
							data: 'ladies-single',
							label: mw.msg('ladies-single-label'),
						} ),
						new OO.ui.MenuOptionWidget( {
							data: 'pairs',
							label: mw.msg('pairs-label'),
						} ),
						new OO.ui.MenuOptionWidget( {
							data: 'dancing',
							label: mw.msg('dancing-label'),
						} ),
						new OO.ui.MenuOptionWidget( {
							data: 'dancing-2010',
							label: mw.msg('dancing-2010-label'),
						} ),
						new OO.ui.MenuOptionWidget( {
							data: 'dancing-1967',
							label: mw.msg('dancing-1967-label'),
						} )
					]
				}
			} );
	
			this.dateShortInput = new mw.widgets.datetime.DateTimeInputWidget( { type: 'date', required: true, clearable: false, } );
			this.dateThirdInput = new mw.widgets.datetime.DateTimeInputWidget( { type: 'date', required: false, clearable: true, } );
			this.dateFreeInput = new mw.widgets.datetime.DateTimeInputWidget( { type: 'date', required: true, clearable: false, } );
	    	this.linkInput = new OO.ui.TextInputWidget( { required: true, validate: 'non-empty' } );
	
			// Create a Fieldset layout.
			var fieldset = new OO.ui.FieldsetLayout();
	
			fieldset.addItems( [ 
				new OO.ui.FieldLayout( this.comp_qid, { label: mw.msg('comp_qid-label'), align: 'left', help: '', } ),
				new OO.ui.FieldLayout( this.discipline, { label: mw.msg('discipline-label'), align: 'left', help: '', } ),
				new OO.ui.FieldLayout( this.dateShortInput, { label: mw.msg('dateshort-label'), align: 'left', help: mw.msg('dateshort-help'), } ),
				new OO.ui.FieldLayout( this.dateThirdInput, { label: mw.msg('datethird-label'), align: 'left', help: mw.msg('datethird-help'), } ),
				new OO.ui.FieldLayout( this.dateFreeInput, { label: mw.msg('datefree-label'), align: 'left', help: '', } ),
				new OO.ui.FieldLayout( this.linkInput, { label: mw.msg('link-label'), align: 'left', help: '', } ),
			] );
	
			this.$element.append( fieldset.$element );
    	};
		OO.inheritClass( MainPageLayout, OO.ui.PageLayout );
		MainPageLayout.prototype.setupOutlineItem = function () {
			this.outlineItem.setLabel( '⛸️' );
		};
		MainPageLayout.prototype.populateMenu = function( data, menuOption, level, parents ) {
			level = level || 0;
			parents = parents || '';
			var list = [];
			var _self = this;
			$.each( data, function( key, value ) {
				var data = '',
						text = '',
						offset = '';
				for(var i=0; i<level; i++) {
					offset = offset + ' ';
				}
				if ( typeof value.text === 'string' ) {
					data = value.text;
					text = value.text;
				}
				else {
					if ( value.text.en !== undefined ) {
						data = value.text.en;
						text = value.text.en;
					}
					if ( value.text[ self.lang ] !== undefined ) {
						text = value.text[ self.lang ];
					}
				}

				if ( menuOption ) {
					list.push( new OO.ui.MenuOptionWidget( { data: data, label: offset + text, } ) );
				}
				else {
					list.push( { data: parents + data, label: offset + text, } );
				}
				
				if ( value.sub !== undefined ) {
					list = list.concat( _self.populateMenu( value.sub, menuOption, level + 1, parents + data + ',' ) );
				}
			} );
			return list;
		};

		this.booklet = new OO.ui.BookletLayout( { outlined: true } );
		
		this.mainPage = new MainPageLayout( 'main' );
		this.booklet.addPages ( [ this.mainPage ] );

		this.$body.append( this.booklet.$element );

    };
    // Use the getActionProcess() method to specify a process to handle the 
    // actions (for the 'save' action, in this example).
    ProcessDialog.prototype.getActionProcess = function ( action ) {
    	var dialog = this;
    	if ( action ) {
    		if ( action === 'save' ) {
    			var form_result = this.booklet.pages.main ;
    			var values = {};
    			values.comp_qid = form_result.comp_qid.getData();
    			values.link = form_result.linkInput.value;
    			var disciplines =  form_result.discipline.menu.items;
    			disciplines.forEach(function(d) {
    				if (d.selected === true) { values.discipline = d.data ; }
    			});
    			values.dateFree = form_result.dateFreeInput.value;
    			values.dateShort = form_result.dateShortInput.value;
    			values.dateThird = form_result.dateThirdInput.value;
    			getCompetitionData(values);
    		}

    		// Close the window
    		return new OO.ui.Process( function () {
    			dialog.close( { action: action } );
    		});
    	}
    	
    	// Fallback to parent handler.
    	return ProcessDialog.super.prototype.getActionProcess.call( this, action );
    };

    // Get dialog height.
    ProcessDialog.prototype.getBodyHeight = function () {
    	return 500;
    };

    // Create a new dialog window.
    var processDialog = new ProcessDialog({ });    

    // Create and append the window manager.
    var windowManager = new OO.ui.WindowManager();
    $( 'body' ).append( windowManager.$element ); 
    windowManager.addWindows( [ processDialog ] );

    
    // Specific functions for this creation helper
    var formatDate = function(date) {
    	// Takes either a date in the YYYY-MM-DD format or the string "now".
    	if (date === "now") {
    		var d = new Date();
    		date = d.toISOString().split('T')[0];
    	}
    	return "+" + date + "T00:00:00Z";
    };
    
    var getCompetitionData = function(values) {
    	if (!values) {
    		mw.notify(mw.msg('no-data'));
    	} else {
    		console.log("values");
    		console.log(values);
    		var api = new mw.Api();
    		
	    	api.get({
	    		"action": "wbgetentities",
	    		"format": "json",
	    		"ids": values.comp_qid,
	    		"props": "labels|claims",
	    		"languages": "en",
	    		"formatversion": "2"
	    	}).done( function ( data ) {
	    		console.log("data");
	    		console.log(data);
	    		var itemData = data["entities"][values.comp_qid];
	    		values.comp_label = itemData.labels.en.value;
	    		values.comp_claims = {};
	    		
	    		// Parsing the mandatory claims
	    		if ("P585" in itemData.claims) { // Date
	    			values.comp_claims.P585 = cleanStatement(itemData.claims.P585[0]);
	    		} else {
	    			mw.notify(mw.msg('missing-mandatory') + "P585");
	    		}
	    		
	    		if ("P17" in itemData.claims) { // Country
	    			values.comp_claims.P17 = cleanStatement(itemData.claims.P17[0]);
	    		} else {
	    			mw.notify(mw.msg('missing-mandatory') + "P17");
	    		}

	    		if ("P276" in itemData.claims) { // Place
	    			values.comp_claims.P276 = cleanStatement(itemData.claims.P276[0]);
	    		} else {
	    			mw.notify(mw.msg('missing-mandatory') + "P276");
	    		}

	    		if ("P664" in itemData.claims) { // Organizer
	    			values.comp_claims.P664 = cleanStatement(itemData.claims.P664[0]);
	    		} else {
	    			mw.notify(mw.msg('missing-mandatory') + "P664");
	    		}
	    		
	    		// Parsing the optional claims
	    		if ("P2348" in itemData.claims) { // Time period
	    			values.comp_claims.P2348 = cleanStatement(itemData.claims.P2348[0]);
	    		}
	    		
	    		if ("P2283" in itemData.claims) { // Uses
	    			values.comp_claims.P2283 = cleanStatement(itemData.claims.P2283[0]);
	    		}

				// Not sure what to do with it
	    		if ("P3085" in itemData.claims) { // Qualifies for event
	    			values.comp_claims.P3085 = cleanStatement(itemData.claims.P3085[0]);
	    		}
	    		
	    		if ("P859" in itemData.claims) { // Sponsor
	    			values.comp_claims.P859 = cleanStatement(itemData.claims.P859[0]);
	    		}
	    		
	    		// Now that we got all the data, we create the items
	    		console.log('final values');
	    		console.log(values);
	    		createItems(values);
	    		
			}).fail( function() {
				mw.notify(mw.msg('comp-data-fail'));
			});
    	}
    };
    
    var getPreviousNext = function(items_list, item, operator) {
		if (operator == "previous") {
			var prop = "P155";
			var value = items_list[items_list.indexOf(item) - 1];
		} else {
			var prop = "P156";
			var value = items_list[items_list.indexOf(item) + 1];
		}
		
		if (value == undefined) {
			var snak = [
                {
                    "snaktype": "novalue",
                    "property": prop,
                    "datatype": "wikibase-item"
                }
            ];
		} else {
			var snak = [
                {
                    "snaktype": "value",
                    "property": prop,
                    "datavalue": {
                        "value": {
                            "entity-type": "item",
                            "id": value
                        },
                        "type": "wikibase-entityid"
                    },
                    "datatype": "wikibase-item"
                }
            ];
		}
		
		return snak;
    }


    var cleanStatement = function(statement) {
    	delete statement.mainsnak.hash;
    	delete statement.id;
    	return statement;
    };

    var createItems = function(data) {
    	if (!data) {
    		mw.notify(mw.msg('no-data'));
    	} else {
    		var api = new mw.Api();

			// Process the data
    		var short_label = "short program";
    		var free_label = "free skating";
    		var short_p31 = "Q2031615";
    		var free_p31 = "Q4380244";
    		var discipline_label = "";
    		var discipline_qid = "";
    		var third_program = false;
    		var summary_message = '[[User:Ash Crow/skating-competitions-creation-helper.js|Skating competitions creation helper]]';
    		
    		var dateFree = formatDate(data.dateFree);
    		var dateShort = formatDate(data.dateShort);
    		var dateThird = formatDate(data.dateThird);

    		
    		
    		var reference_date = formatDate("now");
    		var reference_snak = [{
				"snaks":{
					"P854":[{
						"snaktype":"value",
						"property":"P854",
						"datavalue":{
							"value": data.link,
							"type":"string"
						},
						"datatype":"url"
						
					}],
					"P813":[{
						"snaktype":"value",
						"property":"P813",
						"datavalue":{
							"value":{
								"time": reference_date,
								"timezone":0,
								"before":0,
								"after":0,
								"precision":11,
								"calendarmodel":"http://www.wikidata.org/entity/Q1985727"
							},
							"type":"time"
						},
						"datatype":"time"
					}]
				},
				"snaks-order":[ "P854", "P813" ]
			}];
    		
    		switch (data.discipline) {
    			case "men-single":
    				discipline_qid = "Q4305887";
    				discipline_label = "men's singles";
    				break;
				case "ladies-single":
					discipline_qid = "Q4179462";
    				discipline_label = "ladies' singles";
    				break;
				case "pairs":
					discipline_qid = "Q1682809";
    				discipline_label = "pair skating";
    				break;
				case "dancing":
					discipline_qid = "Q926191";
    				discipline_label = "ice dancing";
    				short_label = "rhythm dance";
    				free_label = "free dance";
    				short_p31 = "Q56276798";
    				free_p31 = "Q4380246";
    				break;
    			case "dancing-2010":
					discipline_qid = "Q926191";
    				discipline_label = "ice dancing";
    				short_label = "short dance";
    				free_label = "free dance";
    				short_p31 = "Q2080304";
    				free_p31 = "Q4380246";
    				break;
    			case "dancing-1967":
					discipline_qid = "Q926191";
    				discipline_label = "ice dancing";
    				short_label = "compulsory dance";
    				free_label = "free dance";
    				short_p31 = "Q1999120";
    				free_p31 = "Q4380246";
    				third_program = true;
    				third_label = "original dance";
    				third_p31 = "Q4336440";
    				break;
    		}
    		
    		// Get the begin and and date for the Discipline item    		
    		var date_order = [dateFree, dateShort];
    		if (third_program == true) {
    			date_order.push(dateThird);
    		}
    		date_order.sort();
    		console.log(date_order);
    		
    		data.free_order = date_order.indexOf(dateFree) + 1;
    		data.short_order = date_order.indexOf(dateShort) + 1;
    		if (third_program == true) {
    			data.third_order = date_order.indexOf(dateThird) + 1;
    		}
  
    		var items = {
    			'competition': {
    				'qid': data.comp_qid,
    				'label': data.comp_label,
    			},
    			'discipline': {
    				'label': data.comp_label + " - " + discipline_label,
    			},
    			'short': {
    				'label': data.comp_label + " - " + discipline_label + " " + short_label,
    			},
    			'free': {
    				'label': data.comp_label + " - " + discipline_label + " " + free_label,
    			}
    		};
    		
    		if (third_program == true) {
    			items['third'] = {
    				'label': data.comp_label + " - " + discipline_label + " " + third_label,
    			};
    		}

    		// Statements for the "discipline" item
			items.discipline.payload = {
				"labels": [{"language": "en","value": items.discipline.label}],
				"descriptions": [{"language": "en","value": "part of a figure skating competition"}],
				"claims":[{
					"mainsnak":{
						"snaktype":"value",
						"property":"P31",
						"datavalue":{
							"value":{
								"entity-type":"item",
								"id":"Q16510064"
							},
							"type":"wikibase-entityid"
						}
					},
					"type":"statement",
					"rank":"normal"
				}, {
					"mainsnak":{
						"snaktype":"value",
						"property":"P641",
						"datavalue":{
							"value":{
								"entity-type":"item",
								"id": discipline_qid
							},
							"type":"wikibase-entityid"
						}
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}, {
					"mainsnak":{
						"snaktype":"value",
						"property":"P361",
						"datavalue":{
							"value":{
								"entity-type":"item",
								"id": items.competition.qid
							},
							"type":"wikibase-entityid"
						}
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}, {
					"mainsnak":{
						"snaktype":"value",
						"property":"P580",
						"datavalue":{
							"value":{
								"time": date_order[0],
								"timezone":0,
								"before":0,
								"after":0,
								"precision":11,
								"calendarmodel":"http://www.wikidata.org/entity/Q1985727"
							},
							"type":"time"
						},
						"datatype": "time",
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}, {
					"mainsnak":{
						"snaktype":"value",
						"property":"P582",
						"datavalue":{
							"value":{
								"time": date_order[date_order.length-1],
								"timezone":0,
								"before":0,
								"after":0,
								"precision":11,
								"calendarmodel":"http://www.wikidata.org/entity/Q1985727"
							},
							"type":"time"
						},
						"datatype": "time",
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}]
			};

			for (p of ["P585", "P2348"]) {
				if ( p in data.comp_claims) {
					items.discipline.payload.claims.push(data.comp_claims[p]);
				}
			}
			
    		// Statements for the "short" item
			items.short.payload = {
				"labels": [{"language": "en","value": items.short.label}],
				"descriptions": [{"language": "en","value": "segment of a figure skating competition"}],
				"claims":[{
					"mainsnak":{
						"snaktype":"value",
						"property":"P31",
						"datavalue":{
							"value":{
								"entity-type":"item",
								"id": short_p31
							},
							"type":"wikibase-entityid"
						}
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}, {
					"mainsnak":{
						"snaktype":"value",
						"property":"P641",
						"datavalue":{
							"value":{
								"entity-type":"item",
								"id": discipline_qid
							},
							"type":"wikibase-entityid"
						}
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}, {
					"mainsnak":{
						"snaktype":"value",
						"property":"P585",
						"datavalue":{
							"value":{
								"time": dateShort,
								"timezone":0,
								"before":0,
								"after":0,
								"precision":11,
								"calendarmodel":"http://www.wikidata.org/entity/Q1985727"
							},
							"type":"time"
						},
						"datatype": "time",
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}]
			};

    		// Statements for the "free" item
			items.free.payload = {
				"labels": [{"language": "en","value": items.free.label}],
				"descriptions": [{"language": "en","value": "segment of a figure skating competition"}],
				"claims":[{
					"mainsnak":{
						"snaktype":"value",
						"property":"P31",
						"datavalue":{
							"value":{
								"entity-type":"item",
								"id": free_p31
							},
							"type":"wikibase-entityid"
						}
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}, {
					"mainsnak":{
						"snaktype":"value",
						"property":"P641",
						"datavalue":{
							"value":{
								"entity-type":"item",
								"id": discipline_qid
							},
							"type":"wikibase-entityid"
						}
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}, {
					"mainsnak":{
						"snaktype":"value",
						"property":"P585",
						"datavalue":{
							"value":{
								"time": dateFree,
								"timezone":0,
								"before":0,
								"after":0,
								"precision":11,
								"calendarmodel":"http://www.wikidata.org/entity/Q1985727"
							},
							"type":"time"
						},
						"datatype": "time",
					},
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				}]
			};

    		// Statements for the optional third item
    		if (third_program == true) {
				items.third.payload = {
					"labels": [{"language": "en","value": items.third.label}],
					"descriptions": [{"language": "en","value": "segment of a figure skating competition"}],
					"claims":[{
						"mainsnak":{
							"snaktype":"value",
							"property":"P31",
							"datavalue":{
								"value":{
									"entity-type":"item",
									"id": third_p31
								},
								"type":"wikibase-entityid"
							}
						},
						"type":"statement",
						"rank":"normal",
						"references": reference_snak
					}, {
						"mainsnak":{
							"snaktype":"value",
							"property":"P641",
							"datavalue":{
								"value":{
									"entity-type":"item",
									"id": discipline_qid
								},
								"type":"wikibase-entityid"
							}
						},
						"type":"statement",
						"rank":"normal",
						"references": reference_snak
					}, {
						"mainsnak":{
							"snaktype":"value",
							"property":"P585",
							"datavalue":{
								"value":{
									"time": dateThird,
									"timezone":0,
									"before":0,
									"after":0,
									"precision":11,
									"calendarmodel":"http://www.wikidata.org/entity/Q1985727"
								},
								"type":"time"
							},
							"datatype": "time",
						},
						"type":"statement",
						"rank":"normal",
						"references": reference_snak
					}]
				};
    		}

			// Statements common to all three/four items
			for (p of ["P17", "P276", "P664", "P2283", "P859"]) {
				if ( p in data.comp_claims) {
					items.discipline.payload.claims.push(data.comp_claims[p]);
					items.short.payload.claims.push(data.comp_claims[p]);
					items.free.payload.claims.push(data.comp_claims[p]);
    				if (third_program == true) {
    					items.third.payload.claims.push(data.comp_claims[p]);
    				}
				}
			}

    		// Create the items and wait for the ajax calls to end to get the ids
			var requests = Array();
			requests.push(api.postWithEditToken({
				'action': "wbeditentity",
				'new': "item",
				'data': JSON.stringify(items.discipline.payload),
				'summary': summary_message
			}));
			requests.push(api.postWithEditToken({
				'action': "wbeditentity",
				'new': "item",
				'data': JSON.stringify(items.short.payload),
				'summary': summary_message
			}));
			requests.push(api.postWithEditToken({
				'action': "wbeditentity",
				'new': "item",
				'data': JSON.stringify(items.free.payload),
				'summary': summary_message
			}));
			if (third_program == true) {
				requests.push(api.postWithEditToken({
					'action': "wbeditentity",
					'new': "item",
					'data': JSON.stringify(items.third.payload),
					'summary': summary_message
				}));
			}

			/* Sandbox items *//*
			{ 0: { entity: { 'id': 'Q4115189' } } },
			{ 0: { entity: { 'id': 'Q13406268' } } },
			{ 0: { entity: { 'id': 'Q15397819' } } }/**/

			var defer = $.when.apply($, requests);
			defer.done(function(){
				// This is executed only after every ajax request has been completed
				created_items = []
			
			    $.each(arguments, function(index, responseData){
			    	created_items.push(responseData[0].entity.id);
			    });

			    var wd_url = "https://www.wikidata.org/wiki/";

				items.discipline.qid = created_items[0];
				notif_ul = '<ul><li><a href="' + wd_url + items.discipline.qid + '">' + items.discipline.qid + ' (' + items.discipline.label + ')</a></li>';
					
		        items.short.qid = created_items[1];
		        notif_ul += '<li><a href="' + wd_url + items.short.qid + '">' + items.short.qid + ' (' + items.short.label + ')</a></li>';
			        
		        items.free.qid = created_items[2];
		        notif_ul += '<li><a href="' + wd_url + items.free.qid + '">' + items.free.qid + ' (' + items.free.label + ')</a></li>';
			        
		        if (third_program == true) {
			        items.third.qid = created_items[3];
			        notif_ul += '<li><a href="' + wd_url + items.third.qid + '">' + items.third.qid + ' (' + items.third.label + ')</a></li>';
		        }
		        
		        notif_ul +='</ul>'
			    
				mw.notify( mw.msg('new-item') );
				mw.notify( $(notif_ul) ); 
    				
				console.log(items);
    				
    			// Now we can start statements that need the items to be linked.
    			// Get the order of the items
    			data.parts_order = ['temp', 'temp'];
    			if (third_program == true) {
    				data.parts_order.push('temp');
    				data.parts_order.splice(data.third_order - 1, 1, items.third.qid);
    			}
    			data.parts_order.splice(data.free_order - 1, 1, items.free.qid);
    			data.parts_order.splice(data.short_order - 1, 1, items.short.qid);
    			console.log(data.parts_order);

				// 1. On the competition item:
				var payload = {
					"claims":[{
						"mainsnak":{
							"snaktype":"value",
							"property":"P527",
							"datavalue":{
								"value":{
									"entity-type":"item",
									"id":items.discipline.qid
								},
								"type":"wikibase-entityid"
							}
						},
						"type":"statement",
						"rank":"normal",
						"references": reference_snak
					}]
				};
				editEntity( items.competition.qid, payload );
    		
				// 2. On the discipline item:
				var payload = {
					"claims":[
						{
    						"mainsnak":{
    							"snaktype":"value",
    							"property":"P527",
    							"datavalue":{
    								"value":{
    									"entity-type":"item",
    									"id":items.short.qid
    								},
    								"type":"wikibase-entityid"
								}
							},
							"qualifiers":{
								"P1545":[{
									"snaktype":"value",
						       		"property":"P1545",
						       		"datavalue": {
						       			"value": data.short_order.toString(),
						       			"type": "string"
						       		},
						       		"datatype": "string"
						       	}]
						    },
						    "qualifiers-order":[ "P1545" ],
							"type":"statement",
							"rank":"normal",
							"references": reference_snak
						}
					]
				};
				
				if (third_program == true) {
					payload.claims.push( {
						"mainsnak":{
							"snaktype":"value",
							"property":"P527",
							"datavalue":{
								"value":{
									"entity-type":"item",
									"id":items.third.qid
								},
								"type":"wikibase-entityid"
							}
						},
						"qualifiers":{
							"P1545":[{
								"snaktype":"value",
					       		"property":"P1545",
					       		"datavalue": {
					       			"value": data.third_order.toString(),
					       			"type": "string"
					       		},
					       		"datatype": "string"
					       	}]
					    },
					    "qualifiers-order":[ "P1545" ],
						"type":"statement",
						"rank":"normal",
						"references": reference_snak
					} );
				}
				
				payload.claims.push( {
					"mainsnak":{
						"snaktype":"value",
						"property":"P527",
						"datavalue":{
							"value":{
								"entity-type":"item",
								"id":items.free.qid
							},
							"type":"wikibase-entityid"
						}
					},
					"qualifiers":{
						"P1545":[{
							"snaktype":"value",
				       		"property":"P1545",
				       		"datavalue": {
				       			"value": data.free_order.toString(),
				       			"type": "string"
				       		},
				       		"datatype": "string"
				       	}]
				    },
				    "qualifiers-order":[ "P1545" ],
					"type":"statement",
					"rank":"normal",
					"references": reference_snak
				} );
				
				console.log(payload);
				editEntity( items.discipline.qid, payload );
				
				// 3. On the short program item:
				var p155_value = getPreviousNext(data.parts_order, items.short.qid, "previous");
				var p156_value = getPreviousNext(data.parts_order, items.short.qid, "next");

				
				var payload = {
					"claims":[
						{
    						"mainsnak":{
    							"snaktype":"value",
    							"property":"P361",
    							"datavalue":{
    								"value":{
    									"entity-type":"item",
    									"id":items.discipline.qid
    								},
							"type":"wikibase-entityid"
								}
							},
							"type":"statement",
							"rank":"normal",
							"qualifiers":{
								"P1545":[{
									"snaktype":"value",
						       		"property":"P1545",
						       		"datavalue": {
						       			"value": data.short_order.toString(),
						       			"type": "string"
						       		},
						       		"datatype": "string"
						       	}],
	                            "P155": p155_value,
	                            "P156": p156_value
						    },
						    "qualifiers-order":[ "P1545", "P155", "P156" ],
							"references": reference_snak
						}
					]
				};
				editEntity( items.short.qid, payload );

				// 4. On the free program item:
				var p155_value = getPreviousNext(data.parts_order, items.free.qid, "previous");
				var p156_value = getPreviousNext(data.parts_order, items.free.qid, "next");

				var payload = {
					"claims":[
						{
    						"mainsnak":{
    							"snaktype":"value",
    							"property":"P361",
    							"datavalue":{
    								"value":{
    									"entity-type":"item",
    									"id":items.discipline.qid
    								},
									"type":"wikibase-entityid",
								}
							},
							"type":"statement",
							"rank":"normal",
							"qualifiers":{
								"P1545":[{
									"snaktype":"value",
						       		"property":"P1545",
						       		"datavalue": {
						       			"value": data.free_order.toString(),
						       			"type": "string"
						       		},
						       		"datatype": "string"
						       	}],
	                            "P155": p155_value,
	                            "P156": p156_value
						    },
						    "qualifiers-order":[ "P1545", "P155", "P156" ],
							"references": reference_snak
						}
					]
				};
				editEntity( items.free.qid, payload );
					
				if (third_program == true) {
					var p155_value = getPreviousNext(data.parts_order, items.third.qid, "previous");
					var p156_value = getPreviousNext(data.parts_order, items.third.qid, "next");

				    // 5. On the third program item:
    				var payload = {
    					"claims":[
    						{
	    						"mainsnak":{
	    							"snaktype":"value",
	    							"property":"P361",
	    							"datavalue":{
	    								"value":{
	    									"entity-type":"item",
	    									"id":items.discipline.qid
	    								},
										"type":"wikibase-entityid",
									}
								},
								"type":"statement",
								"rank":"normal",
								"qualifiers":{
									"P1545":[{
										"snaktype":"value",
							       		"property":"P1545",
							       		"datavalue": {
							       			"value": data.third_order.toString(),
							       			"type": "string"
							       		},
							       		"datatype": "string"
							       	}],
		                            "P155": p155_value,
		                            "P156": p156_value
							    },
							    "qualifiers-order":[ "P1545", "P155", "P156" ],
								"references": reference_snak
							}
						]
					};
					editEntity( items.third.qid, payload );
				}

    			}).fail( function( responseData ) {
    				mw.notify(mw.msg('item-creation-fail' ) + responseData );
    			});
    	}
    }; // end createItems
    
    var editEntity = function(entityId, payload) {
		var api = new mw.Api();
		api.postWithEditToken({
			"action": "wbeditentity",
			"format": "json",
			"id": entityId,
			"data": JSON.stringify(payload)
		}).done( function( data ) {
			console.log('editEntity successed:');
			console.log(data);
			mw.notify(mw.msg('notif-done', entityId));
		}).fail( function( data ) {
			console.log('editEntity failed:');
			console.log(data);
			mw.notify(mw.msg('notif-fail', entityId));
		});
    };
  }); // End mw.loader.using
}

//</nowiki>