MediaWiki:Events-calendar-editor.js
From DFM Wiki
Revision as of 11:45, 27 January 2021 by EricThrift (talk | contribs) (Imported from https://meta.wikimedia.org/wiki/Events_calendar/about)
Note: After saving, 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: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
/* * EventsEditor * * Allow the user to easily add new events to an [[Template:Events calendar]]. * * Author: [[User:0x010C]], [[User:Putnik]] */ //<nowiki> ( function ( mw ) { mw.loader.using( [ 'oojs-ui', 'mediawiki.util', 'mediawiki.widgets.datetime' ], function() { var messages = ( function () { var translations = { en: { addEvent: 'Add an event', add: 'Add!', cancel: 'Cancel', generalInformation: 'General information', eventDetails: 'Event details:', name: 'Name', dateStart: 'Start date', dateEnd: 'End date', description: 'Description', link: 'Event wikipage', location: 'Location', locationHelp: 'If your city is not in the list, it must be added to the list [[Events calendar/parameters.json]]', tags: 'Tags', languageCodes: 'Language codes', repeatRules: 'Repeat rules', repeat: 'Repeat event', repeatHelp: 'Event will be shown in the calendar several times in accordance with the recurrence conditions', frequency: 'Frequency', frequencyHelp: 'Period after which event will occur again; can be extended by the Interval parameter', weekly: 'Weekly', interval: 'Interval', intervalHelp: 'Allows to specify that the event occurs once in N periods, e.g. every 2 weeks', dateUntil: 'Until date', dateUntilHelp: 'The last date when event will take place (optional)', }, fr: { addEvent: 'Ajouter un évènement', add: 'Ajouter !', cancel: 'Annuler', generalInformation: 'Informations générales', eventDetails: 'Détails de l\'évènement :', name: 'Nom', dateStart: 'Date de début', dateEnd: 'Date de fin', description: 'Description', link: 'Page wiki de l\'évènement', location: 'Lieu', locationHelp: 'Si votre ville n\'est pas dans la liste, il faut l\'ajouter à la liste [[Events calendar/parameters.json]]', tags: 'Tags', }, ru: { addEvent: 'Добавить событие', add: 'Добавить!', cancel: 'Отменить', generalInformation: 'Общая информация', eventDetails: 'Детали события:', name: 'Название', dateStart: 'Дата начала', dateEnd: 'Дата окончания', description: 'Описание', link: 'Вики-страница события', location: 'Место', locationHelp: 'Если вашего города нет в списке, его необходимо добавить в список [[Events calendar/parameters.json]]', tags: 'Тэги', languageCodes: 'Коды языков', repeatRules: 'Правила повтора', repeat: 'Повторять событие', repeatHelp: 'Событие будет показано в календаре несколько раз в соответствии с условиями повторения', frequency: 'Частота', frequencyHelp: 'Период, через который событие произойдет снова; может быть расширено параметром «Интервал»', weekly: 'Еженедельно', interval: 'Интервал', intervalHelp: 'Позволяет указать, что событие происходит один раз в N периодов, например каждые 2 недели', dateUntil: 'До даты', dateUntilHelp: 'Последняя дата проведения мероприятия (необязательно)', } }, chain = mw.language.getFallbackLanguageChain(), len = chain.length, ret = {}, i = len - 1; while ( i >= 0 ) { if ( translations.hasOwnProperty( chain[i] ) ) { $.extend( ret, translations[chain[i]] ); } i--; } return ret; }() ); function EventsEditor( config ) { EventsEditor.parent.call( this, config ); } OO.inheritClass( EventsEditor, OO.ui.ProcessDialog ); EventsEditor.static.name = 'eventsEditorDialog'; EventsEditor.static.title = messages.addEvent; EventsEditor.static.size = 'larger'; EventsEditor.static.height = 400; EventsEditor.static.actions = [ { label: messages.add, action: 'save', flags: [ 'primary', 'progressive' ] }, { label: messages.cancel, 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, } ); this.langsInput = 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: messages.eventDetails, } ); fieldset.addItems( [ new OO.ui.FieldLayout( this.nameInput, { label: messages.name, align: 'left', help: '', } ), new OO.ui.FieldLayout( this.dateStartInput, { label: messages.dateStart, align: 'left', help: '', } ), new OO.ui.FieldLayout( this.dateEndInput, { label: messages.dateEnd, align: 'left', help: '', } ), new OO.ui.FieldLayout( this.descriptionInput, { label: messages.description, align: 'left', help: '', } ), new OO.ui.FieldLayout( this.linkInput, { label: messages.link, align: 'left', help: '', } ), new OO.ui.FieldLayout( this.locationInput, { label: messages.location, align: 'left', help: messages.locationHelp, } ), new OO.ui.FieldLayout( this.tagsInput, { label: messages.tags, align: 'left', help: '', } ), new OO.ui.FieldLayout( this.langsInput, { label: messages.languageCodes, align: 'left', help: '', } ), ] ); this.$element.append( fieldset.$element ); }; OO.inheritClass( MainPageLayout, OO.ui.PageLayout ); MainPageLayout.prototype.setupOutlineItem = function () { this.outlineItem.setLabel( messages.generalInformation ); }; 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; }; var RrulePageLayout = function( name, config ) { RrulePageLayout.super.call( this, name, config ); this.repeatSwitch = new OO.ui.ToggleSwitchWidget( { value: false } ); this.freqSelect = new OO.ui.SelectWidget( { items: [ new OO.ui.OptionWidget( { data: 'weekly', label: messages.weekly } ) ] } ); this.freqSelect.selectItemByData( 'weekly' ); this.intervalInput = new OO.ui.NumberInputWidget( { input: { value: 1 }, min: 1, max: 100 } ); this.dateUntilInput = new mw.widgets.datetime.DateTimeInputWidget( { type: 'datetime', clearable: true } ); // Create a Fieldset layout. var fieldset = new OO.ui.FieldsetLayout( { label: messages.repeatRules, } ); fieldset.addItems( [ new OO.ui.FieldLayout( this.repeatSwitch, { label: messages.repeat, align: 'left', help: messages.repeatHelp, } ), new OO.ui.FieldLayout( this.freqSelect, { label: messages.frequency, align: 'left', help: messages.frequencyHelp, } ), new OO.ui.FieldLayout( this.intervalInput, { label: messages.interval, align: 'left', help: messages.intervalHelp, } ), new OO.ui.FieldLayout( this.dateUntilInput, { label: messages.dateUntil, align: 'left', help: messages.dateUntilHelp, } ), ] ); this.$element.append( fieldset.$element ); }; OO.inheritClass( RrulePageLayout, OO.ui.PageLayout ); RrulePageLayout.prototype.setupOutlineItem = function () { this.outlineItem.setLabel( messages.repeatRules ); }; this.booklet = new OO.ui.BookletLayout( { outlined: true } ); this.mainPage = new MainPageLayout( 'main' ); this.rrulePage = new RrulePageLayout( 'rrule' ); this.booklet.addPages( [ this.mainPage, this.rrulePage ] ); 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 ); } if ( data.langs !== undefined ) { dialog.mainPage.langsInput.setValue( data.langs ); } if ( data.rrule !== undefined ) { dialog.rrulePage.repeatSwitch.setValue( true ); dialog.rrulePage.freqSelect.selectItemByData( data.rrule.freq || 'weekly' ); dialog.rrulePage.intervalInput.setValue( data.rrule.interval || 1 ); if ( data.rrule.until !== undefined ) { dialog.rrulePage.dateUntilInput.setValue( new Date( data.rrule.until * 1000 ) ); } } } 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, '_' ) + '@driedfishmatters.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(), langs: this.mainPage.langsInput.getValue(), }; if ( dialog.preload.id !== 0 ) { event.id = dialog.preload.id; event.dtcreated = dialog.preload.dtcreated; } if ( this.rrulePage.repeatSwitch.getValue() ) { event.rrule = { freq: this.rrulePage.freqSelect.getData() || 'weekly', }; var interval = this.rrulePage.intervalInput.getValue(); if ( interval !== 1 ) { event.rrule.interval = interval; } if ( this.rrulePage.dateUntilInput.getValue() ) { event.rrule.until = parseInt( this.rrulePage.dateUntilInput.getValueAsDate().getTime() / 1000 ); } } 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>