Utilisateur:0x010C/script/DataboxEditorDev.js

Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;

Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.
mw.loader.using( [ 'jquery.client', 'jquery.mwEmbedUtil', 'mw.MwEmbedSupport', 'jquery.ui' ] ).done( function () {

    const data_boxes = {
        'fromage': [ 'P18', 'P495', 'P1071', 'P176', 'P186', 'P279', 'P1389', 'P138', 'P1092', 'P2046' ],
    };

	var entity,
		api = new mw.ForeignApi( 'https://www.wikidata.org/w/api.php' ),
		payloads = [];


	//Fetch the the properties we will use according to the infobox used on the article
	function getPropertiesIdFromInfobox() {
	        return data_boxes.fromage;
	}







    /*
     * Property
     */
    Property = function( code, label, description, data_type ) {
        this.code = code;
        this.label = label;
        this.description = description;
        this.data_type = data_type;
        this.claims = [];
        this.node = undefined;
    };
                    
    // Methods
    Property.prototype = {
	    save: function() {
	        for ( var key in this.claims ) {
	            this.claims[ key ].save();
	        }
	    },
	    add_claim: function( guid, value ) {
	        new_claim = new Claim( this, guid, value );
	        this.claims.push( new_claim );
	        return new_claim;
	    },
	    get_claims: function() {
	        return this.claims;
	    },
	    bind: function( node ) {
	        this.node = node;
	    },
    };










    /*
     * Claim
     */
    Claim = function( padre, guid, value ) {
        this.padre = padre;
        this.guid = guid;
        /*
            wikibase-item: {'entity-type':'item','numeric-id':'+node.attr( 'dbe-qid' ).substr(1)+'}
        */
        this.initial_value = value;
        this.is_new = false;
        //TODO: qualifiers
        //TODO: references
        
        if ( this.guid === null ) {
            this.is_new = true;
        }
        this.is_deleted = false;
        this.node = undefined;
    };
    
    //Methods
    Claim.prototype = {
		bind: function( node ) {
	        this.node = node;
	    },
	    current_value: function() {
	        if ( this.node !== undefined ) {
	            switch ( this.padre.data_type ) {
	                case 'wikibase-item':
	                    return {
	                    	'entity-type': 'item',
	                    	'id': this.node.attr( 'dbe-qid' )
	                    };
	            }
	        }
	        return undefined;
	    },
	    remove: function() {
	        this.is_deleted = true;
	    },
	    save: function() {
	        var value = this.current_value();
	        var payload = {};
	        var self = this;
	        
	        if ( this.is_new && this.is_deleted ) {
	            console.log( 'Phantom claim' );
	            return;
	        }
	        else if ( value === undefined ) {
	            console.log( 'Data value of this claim not supported' );
	            return;
	        }
	        else if ( this.is_new ) {
	            console.log( 'New claim' );
	            payload = {
	                action: 'wbcreateclaim',
	                entity: entity.Q,
	                property: this.padre.code,
	                snaktype: 'value',
	                value: JSON.stringify( value ),
	            };
	        }
	        else if ( this.is_deleted ) {
	            console.log( 'Deleted claim' );
	            payload = {
	                action: 'wbremoveclaims',
	                claim: this.guid,
	            };
	        }
	        else if ( JSON.stringify( value ) !== JSON.stringify( this.initial_value ) ) {
	            console.log( 'Updated claim' );
	            payload = {
	                action: 'wbsetclaimvalue',
	                claim: this.guid,
	                snaktype: 'value',
	                value: JSON.stringify( value ),
	            };
	        }
	        else {
	            console.log( 'Unchanged claim' );
	            return;
	        }
	        payload.summary = 'via [[:fr:User:0x010C/script/DataboxEditor.js|DataboxEditor]] from frwiki';
	        payloads.push( payload );
	    },
    };





	Entity = function( Q ) {
		this.Q = Q;
		this.properties = {};
	};
	
	Entity.prototype = {
        getProperties: function( propertiesIds ) {
        	var self = this;
            return api.get( {
		        'action': 'wbgetentities',
		        'ids': propertiesIds.join( '|' ),
		        'format': 'json',
	        } ).then( function( data ) {
                $.each( data.entities, function( key, content ) {
                    var label = ( content.labels.fr !== undefined ? content.labels.fr.value : content.labels.en.value );
                    var description = ( content.descriptions.fr !== undefined ? content.descriptions.fr.value : content.descriptions.en.value );
                    var data_type = content.datatype;
                    
                    self.properties[ key ] = new Property( key, label, description, data_type );
                } );
	        } );
        },
	    getClaims: function() {
	    	var self = this;
	        return api.get( {
	            'action':'wbgetclaims',
	            'entity': this.Q,
	            'format': 'json',
	        } ).then( function( data ) {
	        	$.each( data.claims, function( property, claims ) {
                    $.each( claims, function( key, claim ) {
                        if ( self.properties[ property ] !== undefined ) {
                            self.properties[ property ].add_claim( claim.id, { 'entity-type': 'item', 'id': claim.mainsnak.datavalue.value.id } );
                        }
                    } );
                } );
	        } );
	    },
	    prepare: function() {
	        for ( var key in this.properties ) {
	            this.properties[ key ].save();
	        }
	        console.log( payloads );
	    },
        save: function() {
        	var self = this;
        	if ( payloads.length ) {
        		api.postWithToken( 'csrf', payloads.pop() )
        		.done( function( data ) {
        			console.log( data );
        			self.save();
        		} );
        	}
        	else {
        		 finish();
        	}
        },
	};
    





    data_box_editor = {
        entity: {
            get_labels: function( qid ) {
                return api.get( {
                    'action': 'wbgetentities',
                    'ids': qid,
                    'props': 'labels',
                    'format': 'json',
                } );
            },
        },
        
        //Dialogbox-related functions
        dialog_box: {
            container: undefined,
            prepare: function() {
                form = $( '<form/>' ).attr( 'id', 'dbe-form' );
                $( 'body' ).append(form);

                data_box_editor.dialog_box.container = form.dialog( {
                    autoOpen: false,
                    height: 600,
                    width: 900,
                    modal: true,
                    title:'Databox Editor',
                    buttons: {
                        'Modifier': function() {
                            entity.prepare();
                            entity.save();
                            data_box_editor.dialog_box.container.dialog( 'close' );
                        },
                        'Annuler': function() {
                            data_box_editor.dialog_box.container.dialog( 'close' );
                        }
                    },
                } );
                
                $.each( entity.properties, function( key, property ) {
                    var fieldset = $( '<fieldset>' ).addClass( 'dbe-property' );
                    fieldset.append( $( '<legend>' ).text( property.label ) );
                    fieldset.append( $( '<small>' ).text( property.description ) ).append( '<br>' );
                    switch ( property.data_type ) {
                        case 'wikibase-item':
                            var add = $( '<a>' ).text( '+' ).css( 'color','green' ).click( function() {
                                claim = property.add_claim( null, undefined );
                                data_box_editor.dialog_box.addWikibaseItemField( add, claim );
                            } );
                            fieldset.append( add );
                            $.each( property.get_claims(), function( key, claim ) {
                                data_box_editor.dialog_box.addWikibaseItemField( add, claim );
                            } );
                            break;
                        default:
                            fieldset.append( $( '<span>' ).text( 'Ce type de donnée n\'est pas encore supporté.' ).css( 'color','red' ));
                    }
                    form.append( fieldset );
                    property.bind( fieldset );
                } );
            },
            addWikibaseItemField: function( node, claim ) {
                var input = $( '<input>' ).addClass( 'dbe-claim dbe-wikibase-item' );
                if ( claim.initial_value === undefined ) {
                    input.attr( 'dbe-qid', '' );
                }
                else {
                    input.attr( 'dbe-qid', claim.initial_value.id);
                
                    data_box_editor.entity.get_labels( claim.initial_value.id ).then( function( data ) {
                        label = claim.initial_value.id;
                        if ( data.entities[ claim.initial_value.id ].labels !== undefined ) {
                            if ( data.entities[ claim.initial_value.id ].labels.fr !== undefined ) {
                                label = data.entities[ claim.initial_value.id ].labels.fr.value;
                            }
                            else if ( data.entities[ claim.initial_value.id ].labels.en !== undefined ) {
                                label = data.entities[ claim.initial_value.id ].labels.en.value;
                            }
                        }
                        input.val( label );
                    } );
                }
                var remove = $( '<a>' ).text( '×' ).attr( 'href', '#' ).css( 'color','red' ).click( function() {
                    claim.remove();
                    $( input ).next().remove();
                    $( input ).next().remove();
                    $( input ).next().remove();
                    input.remove();
                } );
                node.before( input ).before( remove ).before( $(  '<br>' ) );
                claim.bind( input );
                data_box_editor.dialog_box.autocomplete( input );
            },
            clear: function() {},
            autocomplete: function (node) {
                node.autocomplete( {
                    minLength: 0,
                    source: function( request, response ) {
                        $.ajax( {
                            'url': 'https://www.wikidata.org/w/api.php',
                            'data': {
                                'action': 'wbsearchentities',
                                'search': request.term,
                                'language': 'fr',
                                'limit': '8',
                                'format': 'json',
                                'origin': 'https://fr.wikipedia.org'
                            },
                            'xhrFields': {
                                'withCredentials': true
                            },
                            'dataType': 'json',
                            'success': function( data ) {
                                list = [];
                                $.each( data.search, function( key, value ) {
                                    list.push( {
                                        label:value.label,
                                        id:value.id,
                                        desc:value.description
                                    } );
                                } );
                                response( list );
                            }
                        } );
                    },
                    select: function( event, ui ) {
                        node.val(ui.item.label);
                        node.attr( 'dbe-qid', ui.item.id);
                        return false;
                    }
                } );
                
                node.autocomplete().data( 'uiAutocomplete' )._renderItem = function( ul, item ) {
                    return $( '<li>' ).append( '<a><b>' + item.label + '</b><br>' + item.desc + '</a>' ).appendTo( ul );
                };
            },
        },
    };

    function init() {
        if ( $( '#t-wikibase a' ).attr( 'href' ) === undefined ) {
            return;
        }
        entity = new Entity( 'Q' + $( '#t-wikibase a' ).attr( 'href' ).split( 'Q' )[ 1 ] );
        entity.getProperties( getPropertiesIdFromInfobox() )
        .then( function() {
            return entity.getClaims();
        } )
        .then( function() {
            data_box_editor.dialog_box.prepare();
            $( '.infobox_v3' ).dblclick( function() {
                data_box_editor.dialog_box.container.dialog( 'open' );
            } );
        } );
    }
    function finish() {
    	var localApi = new mw.Api();
        localApi.post( {
            'action':           'purge',
            'format':           'json',
            'forcelinkupdate':  '1',
            'titles':           mw.config.get( 'wgPageName' ),
        } ).then(function(data) {
            mw.notify( 'Tous a bien été enregistré sur wikidata !', { title: 'Databox Editor' } );
            //location.reload();
        } );
    }
    
    init();
} );