MediaWiki:Gadget-eventsCalendarEditor.js

From Meta, a Wikimedia project coordination wiki

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.
/*
* EventsEditor
*
* Allow the user to easily add new events to an [[Template:Events calendar]].
*
* Author: [[User:0x010C]]
*/
//<nowiki>

( function ( mw ) {
	mw.loader.using( [ 'oojs-ui', 'mediawiki.util', 'mediawiki.widgets.datetime' ], function() {
		function EventsEditor( config ) {
			EventsEditor.parent.call( this, config );
		}

		OO.inheritClass( EventsEditor, OO.ui.ProcessDialog );

		EventsEditor.static.name = 'eventsEditorDialog';
		EventsEditor.static.title = 'Ajouter un évènement';
		EventsEditor.static.size = 'larger';
		EventsEditor.static.height = 400;
		EventsEditor.static.actions = [
			{ label: 'Ajouter !', action: 'save', flags: [ 'primary', 'progressive' ] },
			{ label: 'Annuler', flags: 'safe' }
		];
		EventsEditor.prototype.getBodyHeight = function () {
			return 500;
		};

		EventsEditor.prototype.initialize = function () {
			EventsEditor.parent.prototype.initialize.apply( this, arguments );
			
			var self = this;
			var MainPageLayout = function( name, config ) {
				MainPageLayout.super.call( this, name, config );

				this.nameInput = new OO.ui.TextInputWidget();
				this.dateStartInput = new mw.widgets.datetime.DateTimeInputWidget( { type: 'datetime', clearable: false, } );
				this.dateEndInput = new mw.widgets.datetime.DateTimeInputWidget( { type: 'datetime', clearable: false, } );
				this.descriptionInput = new OO.ui.TextInputWidget( { multiline: true, autosize: true, rows: 4, } );
				this.linkInput = new OO.ui.TextInputWidget();
				this.locationInput = new OO.ui.DropdownInputWidget();
				this.tagsInput = new OO.ui.MenuTagMultiselectWidget( { label: 'TagMultiselectWidget', menu: { items: [] }, allowArbitrary: true, allowDuplicates: false, $overlay: self.$overlay, } );
				//TODO: Change the min/max date of dateStartInput and dateEndInput depending of the value choosen on the other field
				/*this.dateStartInput.on( 'change', function( date ) {
				} );*/
				
				//Populate location and tags inputs
				var _self = this;
				new mw.Api().get( {
					action: 'query',
					prop: 'revisions',
					rvprop: [ 'content' ],
					titles: 'Events calendar/parameters.json',
					formatversion: '2',
				} ).then( function( data ) {
					var content = JSON.parse( data.query.pages[ 0 ].revisions[ 0 ].content );
					
					_self.locationInput.setOptions( _self.populateMenu( content.locations ) );
					_self.tagsInput.addOptions( _self.populateMenu( content.tags ) );
				} );

				// Create a Fieldset layout.
				var fieldset = new OO.ui.FieldsetLayout( { 
					label: 'Détails de l\'évènement :',
				} );

				fieldset.addItems( [ 
					new OO.ui.FieldLayout( this.nameInput, { label: 'Nom', align: 'left', help: '', } ),
					new OO.ui.FieldLayout( this.dateStartInput, { label: 'Date de début', align: 'left', help: '', } ),
					new OO.ui.FieldLayout( this.dateEndInput, { label: 'Date de fin', align: 'left', help: '', } ),
					new OO.ui.FieldLayout( this.descriptionInput, { label: 'Description', align: 'left', help: '', } ),
					new OO.ui.FieldLayout( this.linkInput, { label: 'Page wiki de l\'évènement', align: 'left', help: '', } ),
					new OO.ui.FieldLayout( this.locationInput, { label: 'Lieu', align: 'left', help: 'Si votre ville n\'est pas dans la liste, il faut l\'ajouter à la liste [[Events calendar/parameters.json]]', } ),
					new OO.ui.FieldLayout( this.tagsInput, { label: 'Tags', align: 'left', help: '', } ),
				] );

				this.$element.append( fieldset.$element );
			};
			OO.inheritClass( MainPageLayout, OO.ui.PageLayout );
			MainPageLayout.prototype.setupOutlineItem = function () {
				this.outlineItem.setLabel( 'Informations générales' );
			};
			MainPageLayout.prototype.populateMenu = function( data, 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 ];
						}
					}
					
					list.push( { data: parents + data, label: offset + text, } );
					
					if ( value.sub !== undefined ) {
						list = list.concat( _self.populateMenu( value.sub, 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 );
		};
		EventsEditor.prototype.getSetupProcess = function ( data ) {
			data = data || {};
			var dialog = this;
			
			return EventsEditor.super.prototype.getSetupProcess.call( this, data ).next( function () {
				if ( data.id !== undefined ) {
					dialog.preload = data;
					dialog.mainPage.dateStartInput.setValue( new Date( data.dtstart * 1000 ) );
					dialog.mainPage.dateEndInput.setValue( new Date( data.dtend * 1000 ) );
					dialog.mainPage.nameInput.setValue( data.title || '' );
					dialog.mainPage.descriptionInput.setValue( data.description || '' );
					dialog.mainPage.linkInput.setValue( data.link || '' );
					dialog.mainPage.locationInput.setValue( data.location.join( ',' ) );
					if ( data.tags !== undefined ) {
						dialog.mainPage.tagsInput.setValue( data.tags );
					}
				}
				else {
					dialog.preload = {};
					dialog.preload.id = 0;
				}
			}, this );
		};
		EventsEditor.prototype.getActionProcess = function ( action ) {
			var dialog = this;

			if ( action ) {
				if ( action === 'save' ) {
					var now = parseInt( new Date().getTime()/1000 );
					var event = {
						id: now + '-' + mw.config.get( 'wgUserName' ).replace( / /g, '_' ) + '@meta.wikimedia.org',
						dtcreated: now,
						dtmodified: now,
						dtstart: parseInt( this.mainPage.dateStartInput.getValueAsDate().getTime()/1000 ),
						dtend: parseInt( this.mainPage.dateEndInput.getValueAsDate().getTime()/1000 ),
						title: this.mainPage.nameInput.getValue(),
						description: this.mainPage.descriptionInput.getValue(),
						link: this.mainPage.linkInput.getValue(),
						registration: false, //TODO
						geoloc: {}, //TODO
						location: this.mainPage.locationInput.getValue().split( ',' ),
						tags: this.mainPage.tagsInput.getValue(), 
					};
					if ( dialog.preload.id !== 0 ) {
						event.id = dialog.preload.id;
						event.dtcreated = dialog.preload.dtcreated;
					}
					mw.loader.using( 'mediawiki.api', function() {
						new mw.Api().edit(
							'Events calendar/events.json',
							function ( revision ) {
								var jsonContent = JSON.parse( revision.content );
								var summary;
								if ( dialog.preload.id === 0 ) {
									jsonContent.push( event );
									summary = 'Add new event "' + event.title + '" (' + event.location.join( ', ' ) + ')';
								}
								else {
									$.each( jsonContent, function( key, _ ) {
										if ( jsonContent[ key ].id === event.id ) {
											jsonContent[ key ] = event;
											summary = 'Edit event "' + event.title + '" (' + event.location.join( ', ' ) + ')';
											return false;
										}
									} );
								}
								return {
									text: JSON.stringify( jsonContent, null, 4 ),
									summary: summary,
								};
							}
						)
							.then( function () {
							console.log( 'Saved! ');
						} );
					} );
					return new OO.ui.Process( function () {
						dialog.close( { action: action } );
					} );
				}
			}
			return EventsEditor.parent.prototype.getActionProcess.call( this, action );
		};

		var popup, eventsEditor;
		mw.hook( 'eventscalendar.ready' ).add( function( $eventsCalendar ) {
			if ( popup === undefined ) {
				popup = new OO.ui.WindowManager();
				$( 'body' ).append( popup.$element );
				eventsEditor = new EventsEditor();
				popup.addWindows( [ eventsEditor ] );
			}
			$( '.ec-button-add' ).show().click( function( e ) {
				e.preventDefault();
				popup.openWindow( eventsEditor );
			} );
			$( '.ec-pencil' ).css( 'cursor', 'pointer' ).show().click( function( e ) {
				e.preventDefault();
				var eventId = $( this ).attr( 'id' );
				console.log( eventId );
				new mw.Api().get( {
					action: 'query',
					prop: 'revisions',
					rvprop: [ 'content' ],
					titles: String( 'Events calendar/events.json' ),
					formatversion: '2',
				} ).fail( function( data ) {
					console.log( data );
				} ).then( function( data ) {
					var content  = JSON.parse( data.query.pages[ 0 ].revisions[ 0 ].content );
					$.each( content, function( _, event ) {
						if ( event.id.split( '@' )[ 0 ].replace( ' ', '_' ) === eventId ) {
							console.log( 'found' );
							popup.openWindow( eventsEditor, event );
							return false;
						}
					} );
					
				} );
			} );
		} );
		mw.hook( 'eventscalendar.deleting' ).add( function( $eventsCalendar ) {
			$eventsCalendar.find( '.mw-ui-button' ).off( 'click' );
		} );
	} );
} )( mediaWiki );

//</nowiki>