MediaWiki:Gadget-wadpOrgInfoForm.js
(Redirected from MediaWiki:Gadget-reportOrgInfoForm.js)
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.
/**
* Organizational Information Form (module)
* @author Derick Alangi (WMF)
*/
( function () {
'use strict';
/** M&E staff list */
var users = [
'DAlangi (WMF)',
'DNdubane (WMF)',
'MKaur (WMF)',
'AChina-WMF'
];
var gadgetMsg = {},
getRelevantRawEntry,
parseContentModule,
openWindow,
userLang,
cleanRawEntry,
windowManager,
AffiliateLookupTextInputWidget,
CountryLookupTextInputWidget,
getContentList,
generateKeyValuePair,
sanitizeInput,
convertDateToDdMmYyyyFormat,
convertDateToYyyyMmDdFormat,
fieldDerecognitionDate,
fieldDerecognitionNote,
getModuleContent,
getWikiPageContent,
reportingDueDateCache,
notesOnReportingStatusCache = false;
userLang = mw.config.get( 'wgUserLanguage' );
/**
* When an affiliate is newly created, the affiliate reporting
* due date should be computed for same day a year ahead.
*
* @returns {string}
*/
function getNextReportingDate() {
var date = new Date();
var nextYear = date.getFullYear() + 1;
var month = date.getMonth();
var day = date.getDay();
return new Date( nextYear, month, day ).toISOString();
}
// This is called after translation messages are ready
function initAfterMessages() {
/**
* Provides API parameters for getting module content
* specified by `moduleName`.
*
* @param {string} moduleName
* @return {Object}
*/
getModuleContent = function ( moduleName ) {
return {
action: 'query',
prop: 'revisions',
titles: 'Module:' + moduleName,
rvprop: 'content',
rvlimit: 1
};
};
/**
* Provides API parameters for getting the content
* of a page specified by `pageName`
*
* @param {string} pageName
* @return {Object}
*/
getWikiPageContent = function ( pageName ) {
return {
action: 'query',
prop: 'revisions',
titles: pageName,
rvprop: 'content',
rvlimit: 1
};
};
/**
* Convert date to DD/MM/YYYY format
* @param {string} date
*
* @return {string} date
*/
convertDateToDdMmYyyyFormat = function ( date ) {
var splitted_date;
// Put in a format our lua script will feed on, in DD/MM/YYYY format
splitted_date = date.split('-');
date = splitted_date[2] + "/" + splitted_date[1] + "/" + splitted_date[0];
return date;
};
/**
* Convert date to DD/MM/YYYY format
* @param {string} date
*
* @return {string} date
*/
convertDateToYyyyMmDdFormat = function ( date ) {
var splitted_date;
// Put in a format our calendar OOUI will feed on, in YYYY-MM-DD format
splitted_date = date.split('/');
date = splitted_date[2] + "-" + splitted_date[1] + "-" + splitted_date[0];
return date;
};
/**
* Sanitizes input for saving to wiki
*
* @param {string} s
*
* @return {string}
*/
sanitizeInput = function ( s ) {
return s
.replace( /\\/g, '\\\\' )
.replace( /\n/g, '<br />' );
};
/**
* Creates Lua-style key-value pairs, including converting the
* audiences array into a proper sequential table.
*
* @param {string} k The key
* @param {string} v The value
*
* @return {string}
*/
generateKeyValuePair = function ( k, v ) {
var res, jsonarray;
res = '\t\t'.concat( k, ' = ' );
if ( k === 'dm_structure' ) {
jsonarray = JSON.stringify( v );
// Lua uses { } for "arrays"
jsonarray = jsonarray.replace( '[', '{' );
jsonarray = jsonarray.replace( ']', '}' );
// Style changes (single quotes, spaces after commas)
jsonarray = jsonarray.replace( /\"/g, '\'' );
jsonarray = jsonarray.replace( /,/g, ', ' );
// Basic input sanitation
jsonarray = sanitizeInput( jsonarray );
res += jsonarray;
} else {
v = sanitizeInput( v );
v = v.replace( /'/g, '\\\'' );
res += '\'' + v + '\'';
}
res += ',\n';
return res;
};
/**
* Takes Lua-formatted content from [[Module:Organizational_Informations]] and
* returns an abstract syntax tree.
*
* @param {Object} sourceblob The original API return
* @return {Object} Abstract syntax tree
*/
parseContentModule = function ( sourceblob ) {
var ast, i, raw;
for ( i in sourceblob ) { // should only be one result
raw = sourceblob[ i ].revisions[ 0 ][ '*' ];
ast = luaparse.parse( raw );
return ast.body[ 0 ].arguments[ 0 ].fields;
}
};
/**
* Loops through the abstract syntax tree and returns a specific requested
* entry
*
* @param {Object} entries The abstract syntax tree
* @param {string} uniqueId the entry we want to pick out.
*/
getRelevantRawEntry = function ( entries, uniqueId ) {
var i, j;
// Look through the entries
for ( i = 0; i < entries.length; i++ ) {
// Loop through the individual key-value pairs within each entry
for ( j = 0; j < entries[ i ].value.fields.length; j++ ) {
if (
entries[ i ].value.fields[ j ].key.name === 'unique_id' &&
entries[ i ].value.fields[ j ].value.value === uniqueId
) {
return entries[ i ].value.fields;
}
}
}
};
/**
* Take a raw entry from the abstract syntax tree and make it an object
* that is easier to work with.
*
* @param {Object} relevantRawEntry the raw entry from the AST
* @return {Object} The cleaned up object
*/
cleanRawEntry = function ( relevantRawEntry ) {
var entryData = {},
i, j;
for ( i = 0; i < relevantRawEntry.length; i++ ) {
if ( relevantRawEntry[ i ].key.name === 'dm_structure' ) {
entryData.dm_structure = [];
for (
j = 0;
j < relevantRawEntry[ i ].value.fields.length;
j++
) {
entryData.dm_structure.push(
relevantRawEntry[ i ].value.fields[ j ].value.value
);
}
} else {
entryData[ relevantRawEntry[ i ].key.name ] = relevantRawEntry[ i ].value.value;
}
}
return entryData;
};
/**
* Get an entire content (wikitext) of a given page
*
* @param {Object} sourceblob The original API return
* @return {Object} raw Entire page content (wikitext)
*/
getContentList = function ( sourceblob ) {
var i, raw;
for ( i in sourceblob ) { // should only be one result
raw = sourceblob[ i ].revisions[ 0 ][ '*' ];
return raw;
}
};
/**
* Method to lookup affiliate names from
* [[m:Wikimedia_Affiliates_Data_Portal/MRL/List_Of_All_Wikimedia_Affiliates]]
* and to be used as autocomplete form element in the forms
*/
AffiliateLookupTextInputWidget = function AffiliatesLookupTextInputWidget( config ) {
// Parent constructor
OO.ui.TextInputWidget.call( this, $.extend(
{
icon: 'userGroup',
id: 'group_name',
indicator: 'required',
required: true,
validate: 'text',
value: config,
placeholder: gadgetMsg[ 'group-name-placeholder' ]
}, config
) );
// Mixin constructors
OO.ui.mixin.LookupElement.call( this, config );
};
OO.inheritClass( AffiliateLookupTextInputWidget, OO.ui.TextInputWidget );
OO.mixinClass( AffiliateLookupTextInputWidget, OO.ui.mixin.LookupElement );
/* Get a new request object of the current lookup query value. */
AffiliateLookupTextInputWidget.prototype.getLookupRequest = function () {
var value = this.getValue();
return this.getValidity().then( function () {
// Query the API to get the list of affiliates
return new mw.Api().get(
getWikiPageContent( 'Wikimedia_Affiliates_Data_Portal/MRL/List_Of_All_Wikimedia_Affiliates' )
).then( function ( data ) {
var affiliates, affiliatesContent;
affiliatesContent = getContentList( data.query.pages );
affiliates = affiliatesContent.split(',\n');
// Filter to only affiliates whose names contain the input (case-insensitive)
affiliates = affiliates.filter( function ( v ) {
return v.toLowerCase().indexOf( value.toLowerCase() ) !== -1;
} );
return affiliates;
} );
}, function () {
// No results when the input contains invalid content
return [];
} );
};
/* Pre-process data returned by the request from #getLookupRequest. */
AffiliateLookupTextInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
return response || [];
};
/**
* Get a list of menu option widgets from the (possibly cached) data
* returned by #getLookupCacheDataFromResponse.
*/
AffiliateLookupTextInputWidget.prototype.getLookupMenuOptionsFromData = function ( data ) {
var items = [], i, affiliate;
for ( i = 0; i < data.length; i++ ) {
affiliate = String( data[ i ] );
items.push( new OO.ui.MenuOptionWidget( {
data: affiliate,
label: affiliate
} ) );
}
return items;
};
/**
* Method to lookup affiliate countries names from
* [[m:Wikimedia_Affiliates_Data_Portal/MRL/List_Of_All_Countries]]
* and to be used as autocomplete form element in the OI form.
*/
CountryLookupTextInputWidget = function CountriesLookupTextInputWidget( config ) {
// Parent constructor
OO.ui.TextInputWidget.call( this, $.extend(
{
icon: 'mapPin',
id: 'country',
indicator: 'required',
required: true,
validate: 'text',
value: config,
placeholder: gadgetMsg[ 'affiliate-country-placeholder' ]
}, config
) );
// Mixin constructors
OO.ui.mixin.LookupElement.call( this, config );
};
OO.inheritClass( CountryLookupTextInputWidget, OO.ui.TextInputWidget );
OO.mixinClass( CountryLookupTextInputWidget, OO.ui.mixin.LookupElement );
/* Get a new request object of the current lookup query value. */
CountryLookupTextInputWidget.prototype.getLookupRequest = function () {
var value = this.getValue();
return this.getValidity().then( function () {
// Query the API to get the list of countries
return new mw.Api().get(
getWikiPageContent( 'Wikimedia_Affiliates_Data_Portal/MRL/List_Of_All_Countries' )
).then( function ( data ) {
var countries, countriesContent;
countriesContent = getContentList( data.query.pages );
countries = countriesContent.split(',\n');
// Filter to only countries whose names contain the input (case-insensitive)
countries = countries.filter( function ( v ) {
return v.toLowerCase().indexOf( value.toLowerCase() ) !== -1;
} );
return countries;
} );
}, function () {
// No results when the input contains invalid content
return [];
} );
};
/* Pre-process data returned by the request from #getLookupRequest(). */
CountryLookupTextInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
return response || [];
};
/**
* Get a list of menu option widgets from the (possibly cached) data
* returned by #getLookupCacheDataFromResponse().
*/
CountryLookupTextInputWidget.prototype.getLookupMenuOptionsFromData = function ( data ) {
var items = [], i, country;
for ( i = 0; i < data.length; i++ ) {
country = String( data[ i ] );
items.push( new OO.ui.MenuOptionWidget( {
data: country,
label: country
} ) );
}
return items;
};
/**
* Subclass ProcessDialog
*
* @class OrgInfoEditor
* @extends OO.ui.ProcessDialog
*
* @constructor
* @param {Object} config
*/
function OrgInfoEditor( config ) {
this.affiliate_code = '';
this.group_name = '';
this.org_type = '';
this.region = '';
this.group_country = '';
this.legal_entity = '';
this.mission_changed = '';
this.explanation = '';
this.group_page = '';
this.member_count = '';
this.non_editors_count = '';
this.facebook = '';
this.twitter = '';
this.other = '';
this.dm_structure = []; // dm = decision making
this.group_contact1 = '';
this.group_contact2 = '';
this.board_contacts = '';
this.agreement_date = '';
this.fiscal_year_start = '';
this.fiscal_year_end = '';
this.uptodate_reporting = '';
this.recognition_status = '';
this.me_bypass_ooc_autochecks = '';
this.out_of_compliance_level = '';
this.reporting_due_date = '';
this.dos_stamp = '';
if ( config.unique_id ) {
this.uniqueId = config.unique_id;
}
if ( config.affiliate_code ) {
this.affiliate_code = config.affiliate_code;
}
if ( config.group_name ) {
this.group_name = config.group_name;
}
if ( config.org_type ) {
this.org_type = config.org_type;
}
if ( config.region ) {
this.region = config.region;
}
if ( config.group_country ) {
this.group_country = config.group_country;
}
if ( config.legal_entity ) {
this.legal_entity = config.legal_entity;
}
if ( config.mission_changed ) {
this.mission_changed = config.mission_changed;
}
if ( config.explanation ) {
this.explanation = config.explanation;
}
if ( config.group_page ) {
this.group_page = config.group_page;
}
if ( config.member_count ) {
this.member_count = config.member_count;
}
if ( config.non_editors_count ) {
this.non_editors_count = config.non_editors_count;
}
if ( config.facebook ) {
this.facebook = config.facebook;
}
if ( config.twitter ) {
this.twitter = config.twitter;
}
if ( config.other ) {
this.other = config.other;
}
if ( config.dm_structure ) {
this.dm_structure = config.dm_structure;
}
if ( config.group_contact1 ) {
this.group_contact1 = config.group_contact1;
}
if ( config.group_contact2 ) {
this.group_contact2 = config.group_contact2;
}
if ( config.board_contacts ) {
this.board_contacts = config.board_contacts;
}
if ( config.agreement_date ) {
this.agreement_date = config.agreement_date;
}
if ( config.fiscal_year_start ) {
this.fiscal_year_start = config.fiscal_year_start;
}
if ( config.fiscal_year_end ) {
this.fiscal_year_end = config.fiscal_year_end;
}
if ( config.uptodate_reporting ) {
this.uptodate_reporting = config.uptodate_reporting;
}
if ( config.notes_on_reporting ) {
this.notes_on_reporting = config.notes_on_reporting;
}
if ( config.recognition_status ) {
this.recognition_status = config.recognition_status;
}
if ( config.me_bypass_ooc_autochecks ) {
this.me_bypass_ooc_autochecks = config.me_bypass_ooc_autochecks;
}
if ( config.out_of_compliance_level ) {
this.out_of_compliance_level = config.out_of_compliance_level;
}
if ( config.reporting_due_date ) {
this.reporting_due_date = config.reporting_due_date;
}
if ( config.derecognition_date ) {
this.derecognition_date = config.derecognition_date;
}
if ( config.derecognition_note ) {
this.derecognition_note = config.derecognition_note;
}
if ( config.dos_stamp ) {
this.dos_stamp = config.dos_stamp;
}
OrgInfoEditor.super.call( this, config );
}
OO.inheritClass( OrgInfoEditor, OO.ui.ProcessDialog );
OrgInfoEditor.static.name = 'orginfoEditor';
OrgInfoEditor.static.title = gadgetMsg[ 'org-info-header' ];
OrgInfoEditor.static.actions = [
{
action: 'continue',
modes: 'edit',
label: gadgetMsg[ 'submit-button' ],
flags: [ 'primary', 'constructive' ]
},
{
action: 'cancel',
modes: 'edit',
label: gadgetMsg[ 'cancel-button' ],
flags: 'safe'
}
];
/**
* Use the initialize() method to add content to the dialog's $body,
* to initialize widgets, and to set up event handlers.
*/
OrgInfoEditor.prototype.initialize = function () {
var i,
fieldDMStructureSelected,
dm_structure = [],
fieldMEByPassClone,
fieldMEByPassReasonClone,
fieldUpToDateReportingClone,
fieldOutOfComplianceLevelClone;
OrgInfoEditor.super.prototype.initialize.call( this );
this.content = new OO.ui.PanelLayout( {
padded: true,
expanded: false
} );
// Popup to be used after form validation
this.fieldPopup = new OO.ui.PopupWidget( {
$content: $( '<p style="color: red; text-align: center;">Error! Some required fields are not filled yet. Check and try submitting again.</p>' ),
padded: true,
width: 400,
height: 90,
head: true,
id: 'wadp-popup-widget-position'
} );
this.fieldGroupCode = new OO.ui.TextInputWidget( {
icon: 'code',
value: this.affiliate_code,
type: 'text',
indicator: 'required',
required: true,
placeholder: gadgetMsg[ 'group-code-placeholder' ]
} );
// On edit, pass in the group name as config to be rendered.
this.fieldGroupName = new AffiliateLookupTextInputWidget( this.group_name );
this.fieldOrgType = new OO.ui.DropdownInputWidget( {
options: [
{
data: 'User Group',
label: gadgetMsg[ 'user-group' ]
},
{
data: 'Chapter',
label: gadgetMsg[ 'chapter' ]
},
{
data: 'Thematic Organization',
label: gadgetMsg[ 'thematic-organization' ]
},
{
data: 'Allied or other organization',
label: gadgetMsg[ 'allied-or-other-organization' ]
}
]
} );
if ( this.org_type ) {
this.fieldOrgType.setValue( this.org_type );
}
this.fieldRegion = new OO.ui.DropdownInputWidget( {
options: [
{
data: 'International',
label: gadgetMsg[ 'international' ]
},
{
data: 'Sub-Saharan Africa',
label: gadgetMsg[ 'sub-saharan-africa' ]
},
{
data: 'Asia/Pacific',
label: gadgetMsg[ 'asia-pacific' ]
},
{
data: 'Europe',
label: gadgetMsg[ 'europe' ]
},
{
data: 'MENA',
label: gadgetMsg[ 'mena' ]
},
{
data: 'North America',
label: gadgetMsg[ 'north-america' ]
},
{
data: 'South/Latin America',
label: gadgetMsg[ 'south-latin-america' ]
}
]
} );
if ( this.region ) {
this.fieldRegion.setValue( this.region );
}
this.fieldGroupCountry = new CountryLookupTextInputWidget( this.group_country );
this.fieldLegalEntity = new OO.ui.RadioSelectWidget( {
classes: [ 'radio-inline' ],
items: [
new OO.ui.RadioOptionWidget( {
data: 'Yes',
label: gadgetMsg[ 'yes-response' ]
} ),
new OO.ui.RadioOptionWidget( {
data: 'No',
label: gadgetMsg[ 'no-response' ]
} )
]
} );
// On edit, select the option that was previously submitted
if ( this.legal_entity ) {
this.fieldLegalEntity.selectItemByData( this.legal_entity );
}
this.fieldMissionChanged = new OO.ui.RadioSelectWidget( {
classes: [ 'radio-inline' ],
items: [
new OO.ui.RadioOptionWidget( {
data: 'Yes',
label: gadgetMsg[ 'yes-response' ]
} ),
new OO.ui.RadioOptionWidget( {
data: 'No',
label: gadgetMsg[ 'no-response' ]
} ),
new OO.ui.RadioOptionWidget( {
data: 'Not sure',
label: gadgetMsg[ 'not-sure-response' ]
} )
]
} );
// On edit, select the option that was previously submitted
if ( this.mission_changed ) {
this.fieldMissionChanged.selectItemByData( this.mission_changed );
}
this.fieldExplanation = new OO.ui.MultilineTextInputWidget( {
icon: 'textFlow',
value: this.explanation,
rows: 3,
placeholder: gadgetMsg[ 'explanation-text' ]
} );
this.fieldGroupMembershipPage = new OO.ui.TextInputWidget( {
icon: 'link',
value: this.group_page,
placeholder: gadgetMsg[ 'group-membership-page-link' ]
} );
this.fieldEditorsMemberCount = new OO.ui.TextInputWidget( {
icon: 'clock',
value: this.member_count,
type: 'number',
indicator: 'required',
required: true,
placeholder: gadgetMsg[ 'editors-count-placeholder' ]
} );
this.fieldNonEditorsMemberCount = new OO.ui.TextInputWidget( {
icon: 'clock',
value: this.non_editors_count,
type: 'number',
indicator: 'required',
required: true,
placeholder: gadgetMsg[ 'non-editors-count-placeholder' ]
} );
this.fieldFacebook = new OO.ui.TextInputWidget( {
labelPosition: 'before',
icon: 'link',
type: 'url',
value: this.facebook,
label: 'Facebook: '
} );
this.fieldTwitter = new OO.ui.TextInputWidget( {
labelPosition: 'before',
classes: [ 'full-width' ],
icon: 'link',
type: 'url',
value: this.twitter,
label: 'Twitter: '
} );
this.fieldOther = new OO.ui.TextInputWidget( {
labelPosition: 'before',
classes: [ 'full-width' ],
icon: 'link',
type: 'url',
value: this.other,
label: 'Blog/news: '
} );
fieldDMStructureSelected = [];
for ( i = 0; i < dm_structure.length; i++ ) {
fieldDMStructureSelected.push( {
data: dm_structure[ i ],
label: gadgetMsg[ dm_structure[ i ].toLowerCase().replace( / /g, '-' ) + '-structure' ]
} );
}
this.fieldDecisionMakingStructure = new OO.ui.CheckboxMultiselectWidget( {
classes: [ 'checkbox-inline' ],
selected: fieldDMStructureSelected,
items: [
new OO.ui.CheckboxMultioptionWidget( {
data: 'Board',
label: gadgetMsg[ 'board-structure' ]
} ),
new OO.ui.CheckboxMultioptionWidget( {
data: 'Consensus Decision Making',
label: gadgetMsg[ 'consensus-decision-making-structure' ]
} ),
new OO.ui.CheckboxMultioptionWidget( {
data: 'Democratic Process',
label: gadgetMsg[ 'democratic-process-structure' ]
} ),
new OO.ui.CheckboxMultioptionWidget( {
data: 'No Shared Structure',
label: gadgetMsg[ 'no-shared-structure-structure' ]
} )
]
} );
// On edit, select the option that was previously submitted
if ( this.dm_structure ) {
this.fieldDecisionMakingStructure.selectItemsByData( this.dm_structure );
}
this.fieldGroupContact1 = new OO.ui.TextInputWidget( {
labelPosition: 'before',
label: 'User:',
value: this.group_contact1.substring(5), // Ignore "User:" part.
classes: [ 'full-width' ],
indicator: 'required',
required: true
} );
this.fieldGroupContact2 = new OO.ui.TextInputWidget( {
labelPosition: 'before',
label: 'User:',
value: this.group_contact2.substring(5), // Ignore "User:" part.
classes: [ 'full-width' ],
indicator: 'required',
required: true
} );
this.fieldBoardContacts = new OO.ui.MultilineTextInputWidget( {
icon: 'userContributions',
value: this.board_contacts,
rows: 3,
placeholder: gadgetMsg[ 'board-contacts' ]
} );
this.fieldAgreementDate = new mw.widgets.DateInputWidget( {
value: this.agreement_date ? convertDateToYyyyMmDdFormat( this.agreement_date ) : this.agreement_date,
classes: [ 'full-width' ],
placeholderLabel: gadgetMsg[ 'agreement-date' ],
indicator: 'required',
required: true
} );
this.fieldFiscalYearStart = new OO.ui.TextInputWidget( {
value: this.fiscal_year_start,
classes: [ 'full-width' ],
placeholder: gadgetMsg[ 'fiscal-year-start' ]
} );
this.fieldFiscalYearEnd = new OO.ui.TextInputWidget( {
value: this.fiscal_year_end,
classes: [ 'full-width' ],
placeholder: gadgetMsg[ 'fiscal-year-end' ]
} );
fieldUpToDateReportingClone = this.fieldUpToDateReporting = new OO.ui.DropdownInputWidget( {
options: [
{
data: 'Tick',
label: gadgetMsg[ 'tick' ]
},
{
data: 'Cross',
label: gadgetMsg[ 'cross' ]
},
{
data: 'Tick-N',
label: gadgetMsg[ 'tick-n' ]
},
{
data: 'Cross-N',
label: gadgetMsg[ 'cross-n' ]
}
]
} );
if ( this.uptodate_reporting ) {
this.fieldUpToDateReporting.setValue( this.uptodate_reporting );
}
this.fieldRecognitionStatus = new OO.ui.DropdownInputWidget( {
options: [
{
data: 'recognised',
label: gadgetMsg[ 'affiliate-recognised' ]
},
{
data: 'derecognised',
label: gadgetMsg[ 'affiliate-derecognised' ]
},
{
data: 'deferred',
label: gadgetMsg[ 'org-info-deferred-state' ]
},
{
data: 'suspended',
label: gadgetMsg[ 'affiliate-suspended' ]
}
]
} );
if ( this.recognition_status ) {
this.fieldRecognitionStatus.setValue( this.recognition_status );
}
fieldMEByPassClone = this.fieldMEByPassOOCAutoChecks = new OO.ui.DropdownInputWidget( {
options: [
{ data: 'No', },
{ data: 'Yes', }
]
} );
if ( this.me_bypass_ooc_autochecks ) {
this.fieldMEByPassOOCAutoChecks.setValue( this.me_bypass_ooc_autochecks );
}
fieldMEByPassReasonClone = this.fieldMEByPassReason = new OO.ui.DropdownInputWidget( {
options: [
{ data: 'Report past due' },
{ data: 'Old report submitted' },
{ data: 'Empty report submitted' },
{ data: 'Incomplete report submitted' },
{ data: 'Other - Specify custom notes below' }
]
} );
fieldMEByPassReasonClone.toggle();
if ( this.notes_on_reporting ) {
this.fieldMEByPassReason.setValue( this.notes_on_reporting );
fieldMEByPassReasonClone.toggle(true);
}
this.fieldNotesOnReporting = new OO.ui.TextInputWidget( {
maxLength: 60,
placeholder: gadgetMsg[ 'org-info-notes-on-reporting-placeholder' ]
} );
fieldOutOfComplianceLevelClone = this.fieldOutOfComplianceLevel = new OO.ui.DropdownInputWidget( {
options: [
{ data: '0' },
{ data: '1' },
{ data: '2' },
{ data: '3' },
{ data: '4' },
{ data: '5' },
{ data: '6' }
]
} );
if ( this.out_of_compliance_level ) {
this.fieldOutOfComplianceLevel.setValue(
this.out_of_compliance_level ? this.out_of_compliance_level : 'N/A'
);
}
// Cache the reporting due date year for event usage.
reportingDueDateCache = this.reporting_due_date;
fieldMEByPassClone.on('change', function () {
if ( fieldMEByPassClone.getValue() === 'Yes' ) {
fieldMEByPassReasonClone.toggle(true);
} else {
// Also reset the reporting due date if compliance status
// is marked as compliant and OOC level moves to 0
if ( fieldUpToDateReportingClone.getValue() === "Tick" &&
fieldOutOfComplianceLevelClone.getValue() === '0'
) {
var yearPlusOne;
yearPlusOne = new Date( reportingDueDateCache );
reportingDueDateCache = ( new Date( yearPlusOne.setFullYear( yearPlusOne.getFullYear() + 1 ) ) )
.toISOString();
notesOnReportingStatusCache = true;
}
fieldMEByPassReasonClone.toggle(false);
}
} );
fieldDerecognitionDate = this.fieldDerecognitionDate = new mw.widgets.DateInputWidget( {
value: this.derecognition_date ? convertDateToYyyyMmDdFormat( this.derecognition_date ) : this.derecognition_date,
classes: [ 'full-width' ],
placeholderLabel: gadgetMsg[ 'derecognition-date' ],
indicator: 'required',
required: true
} );
fieldDerecognitionNote = this.fieldDerecognitionNote = new OO.ui.TextInputWidget( {
value: this.derecognition_note,
placeholder: gadgetMsg[ 'derecognition-note' ]
} );
fieldDerecognitionDate.toggle( false );
fieldDerecognitionNote.toggle( false );
this.fieldRecognitionStatus.on( 'change', function ( status ) {
if ( status === 'derecognised' ) {
fieldDerecognitionDate.toggle( true );
fieldDerecognitionNote.toggle( true );
} else {
fieldDerecognitionDate.toggle( false );
fieldDerecognitionNote.toggle( false );
}
} );
/* Get today's date in YYYY/MM/DD format. dos stands for "date of submission" */
this.dos_stamp = new Date().toJSON().slice(0,10).replace(/-/g,'/');
this.fieldDateOfSubmission = new OO.ui.TextInputWidget( {
value: this.dos_stamp,
type: 'hidden'
} );
// Append things to fieldSet
this.fieldSet = new OO.ui.FieldsetLayout( {
items: [
new OO.ui.FieldLayout(
this.fieldPopup, {}
),
new OO.ui.FieldLayout(
this.fieldGroupName,
{
label: gadgetMsg[ 'group-name' ],
align: 'top',
help: gadgetMsg[ 'group-name-tip' ]
}
)
]
} );
if ( users.indexOf( mw.config.values.wgUserName ) > -1 ) {
this.fieldSet.addItems( [
new OO.ui.FieldLayout(
this.fieldGroupCode,
{
label: gadgetMsg['group-code-label'],
align: 'top'
}
)
] );
}
this.fieldSet.addItems( [
new OO.ui.FieldLayout(
this.fieldOrgType,
{
label: gadgetMsg[ 'identify-your-organization' ],
align: 'top'
}
)
] );
if ( users.indexOf( mw.config.values.wgUserName ) > -1 ) {
this.fieldSet.addItems( [
new OO.ui.FieldLayout(
this.fieldRegion,
{
label: gadgetMsg[ 'group-region' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldGroupCountry,
{
label: gadgetMsg[ 'affiliate-country' ],
align: 'top'
}
),
] );
}
this.fieldSet.addItems( [
new OO.ui.FieldLayout(
this.fieldLegalEntity,
{
label: gadgetMsg[ 'legal-entity-or-not' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldMissionChanged,
{
label: gadgetMsg[ 'has-group-mission-changed' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldExplanation,
{
label: gadgetMsg[ 'mission-changed-or-unsure-explanation' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldGroupMembershipPage,
{
label: gadgetMsg[ 'group-membership-page' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldEditorsMemberCount,
{
label: gadgetMsg[ 'editors-count' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldNonEditorsMemberCount,
{
label: gadgetMsg[ 'non-editors-count' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldFacebook,
{
label: gadgetMsg[ 'social-media-links' ],
align: 'top',
help: gadgetMsg[ 'facebook-link-help' ]
}
),
new OO.ui.FieldLayout(
this.fieldTwitter,
{ align: 'inline' }
),
new OO.ui.FieldLayout(
this.fieldOther,
{ align: 'inline' }
),
new OO.ui.FieldLayout(
this.fieldDecisionMakingStructure,
{
label: gadgetMsg[ 'decision-making-structure' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldGroupContact1,
{
label: gadgetMsg[ 'group-contact-one-label' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldGroupContact2,
{
label: gadgetMsg[ 'group-contact-two-label' ],
align: 'top'
}
),
new OO.ui.FieldLayout(
this.fieldBoardContacts,
{
label: gadgetMsg[ 'board-members' ],
align: 'top',
help: gadgetMsg[ 'board-members-tip' ]
}
),
] );
if ( users.indexOf( mw.config.values.wgUserName ) > -1 ) {
this.fieldSet.addItems( [
new OO.ui.FieldLayout(
this.fieldAgreementDate,
{
label: gadgetMsg[ 'recognition-date-of-affiliate' ],
align: 'top',
help: gadgetMsg[ 'recognition-date-tip' ]
}
),
new OO.ui.FieldLayout(
this.fieldFiscalYearStart,
{
label: gadgetMsg[ 'fiscal-year-of-affiliate' ],
align: 'top',
placeholder: gadgetMsg[ 'fiscal-year-start' ]
}
),
new OO.ui.FieldLayout(
this.fieldFiscalYearEnd,
{
label: '',
align: 'top',
placeholder: gadgetMsg[ 'fiscal-year-end' ]
}
),
new OO.ui.FieldLayout(
this.fieldUpToDateReporting,
{
label: gadgetMsg[ 'compliance-status-of-affiliate' ],
align: 'top',
}
),
new OO.ui.FieldLayout(
this.fieldOutOfComplianceLevel,
{
label: gadgetMsg[ 'out-of-compliance-level' ],
align: 'top',
}
),
new OO.ui.FieldLayout(
this.fieldRecognitionStatus,
{
label: gadgetMsg[ 'recognition-status-label' ],
align: 'top',
}
),
new OO.ui.FieldLayout(
this.fieldMEByPassOOCAutoChecks,
{
label: gadgetMsg[ 'bypass-ooc-autochecks' ],
align: 'top',
}
),
new OO.ui.FieldLayout(
this.fieldMEByPassReason,
{
label: gadgetMsg[ 'bypass-ooc-autochecks-reason' ],
align: 'top',
}
),
new OO.ui.FieldLayout(
this.fieldNotesOnReporting,
{
label: gadgetMsg[ 'org-info-notes-on-reporting' ],
align: 'top',
}
),
new OO.ui.FieldLayout(
this.fieldDerecognitionDate,
{
align: 'top',
}
),
new OO.ui.FieldLayout(
this.fieldDerecognitionNote,
{
align: 'top',
}
),
] );
}
// When everything is done
this.content.$element.append( this.fieldSet.$element );
this.$body.append( this.content.$element );
};
/**
* Set custom height for the modal window
*
*/
OrgInfoEditor.prototype.getBodyHeight = function () {
return 700;
};
/**
* In the event "Select" is pressed
*
*/
OrgInfoEditor.prototype.getActionProcess = function ( action ) {
var dialog = this, allRequiredFieldsAvailable = false;
// Before submitting the form, check that all required fields indeed
// have values before we call saveItem(). Otherwise, don't close the
// form but instead reveal which input fields are not yet filled.
if( dialog.fieldGroupName.getValue() &&
dialog.fieldGroupCode.getValue() &&
dialog.fieldEditorsMemberCount.getValue() &&
dialog.fieldNonEditorsMemberCount.getValue() &&
dialog.fieldGroupCountry.getValue() &&
dialog.fieldLegalEntity.findSelectedItem().getData() &&
dialog.fieldMissionChanged.findSelectedItem().getData() &&
dialog.fieldEditorsMemberCount.getValue() &&
dialog.fieldNonEditorsMemberCount.getValue() &&
/* TODO: Make group contacts optional for now
M&E need to submit other org info without this. */
// dialog.fieldGroupContact1.getValue() &&
// dialog.fieldGroupContact2.getValue() &&
dialog.fieldAgreementDate.getValue()
) {
allRequiredFieldsAvailable = true;
}
if ( action === 'continue' && allRequiredFieldsAvailable ) {
return new OO.ui.Process( function () {
dialog.saveItem();
} );
} else if ( action === 'continue' && allRequiredFieldsAvailable === false ) {
return new OO.ui.Process( function () {
dialog.fieldPopup.toggle( true );
} );
} else {
return new OO.ui.Process( function () {
dialog.close();
} );
}
};
/**
* Save the changes to [[Module:Organizational_Informations]] page.
*/
OrgInfoEditor.prototype.saveItem = function ( deleteFlag ) {
var dialog = this;
dialog.pushPending();
new mw.Api().get( getModuleContent( 'Organizational_Informations' ) ).then( function ( data ) {
new mw.Api().get(
getModuleContent( 'Organizational_Informations/Membership_Infos' )
).then( function ( existingGroupContacts ) {
var i, j,
insertInPlace,
processWorkingEntry,
editSummary,
manifest = [],
workingEntry,
entries,
mrl_affiliates = '',
membershipInfosEntries,
membershipInfosManifest = [],
insertInPlaceGC;
/**
* Compares a given [[Module:Organizational_Informations]] entry against the edit fields
* and applies changes where relevant.
*
* @param {Object} workingEntry the entry being worked on
* @return {Object} The same entry but with modifications
*/
processWorkingEntry = function ( workingEntry ) {
if ( dialog.fieldGroupCode.getValue() ) {
workingEntry.affiliate_code = dialog.fieldGroupCode.getValue();
}
if ( dialog.fieldGroupName.getValue() ) {
workingEntry.group_name = dialog.fieldGroupName.getValue();
} else if ( !dialog.fieldGroupName.getValue() && workingEntry.group_name ) {
delete workingEntry.group_name;
}
if ( dialog.fieldOrgType.getValue() ) {
workingEntry.org_type = dialog.fieldOrgType.getValue();
} else if ( !dialog.fieldOrgType.getValue() && workingEntry.org_type ) {
delete workingEntry.org_type;
}
if ( dialog.fieldRegion.getValue() ) {
workingEntry.region = dialog.fieldRegion.getValue();
} else if ( !dialog.fieldRegion.getValue() && workingEntry.region ) {
delete workingEntry.region;
}
if ( dialog.fieldGroupCountry.getValue() ) {
workingEntry.group_country = dialog.fieldGroupCountry.getValue();
} else if ( !dialog.fieldGroupCountry.getValue() && workingEntry.group_country ) {
delete workingEntry.group_country;
}
if ( dialog.fieldLegalEntity.findSelectedItem().getData() ) {
workingEntry.legal_entity = dialog.fieldLegalEntity.findSelectedItem().getData();
} else if ( !dialog.findSelectedItem().getData() && workingEntry.legal_entity ) {
delete workingEntry.legal_entity;
}
if ( dialog.fieldMissionChanged.findSelectedItem().getData() ) {
workingEntry.mission_changed = dialog.fieldMissionChanged.findSelectedItem().getData();
} else if ( !dialog.fieldMissionChanged.findSelectedItem().getData() &&
workingEntry.mission_changed ) {
delete workingEntry.mission_changed;
}
if ( dialog.fieldExplanation.getValue() ) {
workingEntry.explanation = dialog.fieldExplanation.getValue();
} else if ( !dialog.fieldExplanation.getValue() && workingEntry.explanation ) {
delete workingEntry.explanation;
}
if ( dialog.fieldGroupMembershipPage.getValue() ) {
workingEntry.group_page = dialog.fieldGroupMembershipPage.getValue();
} else if ( !dialog.fieldGroupMembershipPage.getValue() && workingEntry.group_page ) {
delete workingEntry.group_page;
}
if ( dialog.fieldEditorsMemberCount.getValue() ) {
workingEntry.member_count = dialog.fieldEditorsMemberCount.getValue();
} else if ( !dialog.fieldEditorsMemberCount.getValue() && workingEntry.member_count ) {
delete workingEntry.member_count;
}
if ( dialog.fieldNonEditorsMemberCount.getValue() ) {
workingEntry.non_editors_count = dialog.fieldNonEditorsMemberCount.getValue();
} else if ( !dialog.fieldNonEditorsMemberCount.getValue() && workingEntry.non_editors_count ) {
delete workingEntry.non_editors_count;
}
if ( dialog.fieldFacebook.getValue() ) {
workingEntry.facebook = dialog.fieldFacebook.getValue();
} else if ( !dialog.fieldFacebook.getValue() && workingEntry.facebook ) {
delete workingEntry.facebook;
}
if ( dialog.fieldTwitter.getValue() ) {
workingEntry.twitter = dialog.fieldTwitter.getValue();
} else if ( !dialog.fieldTwitter.getValue() && workingEntry.twitter ) {
delete workingEntry.twitter;
}
if ( dialog.fieldOther.getValue() ) {
workingEntry.other = dialog.fieldOther.getValue();
} else if ( !dialog.fieldOther.getValue() && workingEntry.other ) {
delete workingEntry.other;
}
if ( dialog.fieldDecisionMakingStructure.findSelectedItemsData() ) {
workingEntry.dm_structure = dialog.fieldDecisionMakingStructure.findSelectedItemsData();
} else if ( !dialog.fieldDecisionMakingStructure.findSelectedItemsData() && workingEntry.dm_structure ) {
delete workingEntry.dm_structure;
}
if ( dialog.fieldGroupContact1.getValue() ) {
workingEntry.group_contact1 = dialog.fieldGroupContact1.getValue();
} else if ( !dialog.fieldGroupContact1.getValue() && workingEntry.group_contact1 ) {
delete workingEntry.group_contact1;
}
if ( dialog.fieldGroupContact2.getValue() ) {
workingEntry.group_contact2 = dialog.fieldGroupContact2.getValue();
} else if ( !dialog.fieldGroupContact2.getValue() && workingEntry.group_contact2 ) {
delete workingEntry.group_contact2;
}
if ( dialog.fieldBoardContacts.getValue() ) {
workingEntry.board_contacts = dialog.fieldBoardContacts.getValue();
} else if ( !dialog.fieldBoardContacts.getValue() && workingEntry.board_contacts ) {
delete workingEntry.board_contacts;
}
if ( dialog.fieldAgreementDate.getValue() ) {
workingEntry.agreement_date = convertDateToDdMmYyyyFormat( dialog.fieldAgreementDate.getValue() );
} else if ( !dialog.fieldAgreementDate.getValue() && workingEntry.agreement_date ) {
delete workingEntry.agreement_date;
}
if ( dialog.fieldFiscalYearStart.getValue() ) {
workingEntry.fiscal_year_start = dialog.fieldFiscalYearStart.getValue();
} else if ( !dialog.fieldFiscalYearStart.getValue() && workingEntry.fiscal_year_start ) {
delete workingEntry.fiscal_year_start;
}
if ( dialog.fieldFiscalYearEnd.getValue() ) {
workingEntry.fiscal_year_end = dialog.fieldFiscalYearEnd.getValue();
} else if ( !dialog.fieldFiscalYearEnd.getValue() && workingEntry.fiscal_year_end ) {
delete workingEntry.fiscal_year_end;
}
if ( dialog.fieldUpToDateReporting.getValue() ) {
workingEntry.uptodate_reporting = dialog.fieldUpToDateReporting.getValue();
} else if ( !dialog.fieldUpToDateReporting.getValue() && workingEntry.uptodate_reporting ) {
delete workingEntry.uptodate_reporting;
}
if ( dialog.fieldRecognitionStatus.getValue() ) {
workingEntry.recognition_status = dialog.fieldRecognitionStatus.getValue();
} else if ( !dialog.fieldRecognitionStatus.getValue() && workingEntry.recognition_status ) {
delete workingEntry.recognition_status;
}
if ( dialog.fieldMEByPassOOCAutoChecks.getValue() === "Yes" ) {
workingEntry.me_bypass_ooc_autochecks = dialog.fieldMEByPassOOCAutoChecks.getValue();
if ( dialog.fieldNotesOnReporting.getValue() ) {
workingEntry.notes_on_reporting = dialog.fieldNotesOnReporting.getValue();
} else {
workingEntry.notes_on_reporting = dialog.fieldMEByPassReason.getValue();
}
} else if ( dialog.fieldMEByPassOOCAutoChecks.getValue() === "No" ) {
workingEntry.me_bypass_ooc_autochecks = dialog.fieldMEByPassOOCAutoChecks.getValue();
} else if ( !dialog.fieldMEByPassOOCAutoChecks.getValue() && workingEntry.me_bypass_ooc_autochecks ) {
delete workingEntry.me_bypass_ooc_autochecks;
}
if ( dialog.fieldOutOfComplianceLevel.getValue() ) {
workingEntry.out_of_compliance_level = dialog.fieldOutOfComplianceLevel.getValue();
} else if ( !dialog.fieldOutOfComplianceLevel.getValue() && workingEntry.out_of_compliance_level ) {
delete workingEntry.out_of_compliance_level;
}
if ( reportingDueDateCache ) {
workingEntry.reporting_due_date = reportingDueDateCache;
if ( notesOnReportingStatusCache ) {
workingEntry.notes_on_reporting = '';
}
}
// Invalidate cache to avoid data corruption
reportingDueDateCache = null;
notesOnReportingStatusCache = false;
if ( dialog.fieldDerecognitionDate.getValue() ) {
workingEntry.derecognition_date = convertDateToDdMmYyyyFormat( dialog.fieldDerecognitionDate.getValue() );
} else if ( !dialog.fieldDerecognitionDate.getValue() && workingEntry.derecognition_date ) {
delete workingEntry.derecognition_date;
}
if ( dialog.fieldDerecognitionNote.getValue() ) {
workingEntry.derecognition_note = dialog.fieldDerecognitionNote.getValue();
} else if ( !dialog.fieldDerecognitionNote.getValue() && workingEntry.derecognition_note ) {
delete workingEntry.derecognition_note;
}
if ( dialog.fieldDateOfSubmission.getValue() ) {
workingEntry.dos_stamp = dialog.fieldDateOfSubmission.getValue();
} else if ( !dialog.fieldDateOfSubmission.getValue() && workingEntry.dos_stamp ) {
delete workingEntry.dos_stamp;
}
return workingEntry;
};
// Cycle through existing entries. If we are editing an existing
// entry, that entry will be modified in place.
entries = parseContentModule( data.query.pages );
membershipInfosEntries = parseContentModule( existingGroupContacts.query.pages );
for ( i = 0; i < membershipInfosEntries.length; i++ ) {
membershipInfosManifest.push( cleanRawEntry( membershipInfosEntries[i].value.fields ) );
}
for ( i = 0; i < entries.length; i++ ) {
workingEntry = cleanRawEntry( entries[ i ].value.fields );
if ( workingEntry.group_name === dialog.group_name ) {
var newGroupContact1,
newGroupContact2,
oldGroupContact1,
oldGroupContact2,
newEditorsCount,
newNonEditorsCount,
oldEditorsCount,
oldNonEditorsCount,
membershipObj = {},
oldMembershipInfos = {};
newGroupContact1 = dialog.fieldGroupContact1.getValue().normalize();
newGroupContact2 = dialog.fieldGroupContact2.getValue().normalize()
if ( workingEntry.group_contact1 ) {
oldGroupContact1 = workingEntry.group_contact1.normalize();
} else {
// fallback to new name
oldGroupContact1 = newGroupContact1;
}
if ( workingEntry.group_contact2 ) {
oldGroupContact2 = workingEntry.group_contact2.normalize();
} else {
// fallback to new name
oldGroupContact2 = newGroupContact2;
}
newEditorsCount = dialog.fieldEditorsMemberCount.getValue();
newNonEditorsCount = dialog.fieldNonEditorsMemberCount.getValue();
oldEditorsCount = workingEntry.member_count;
oldNonEditorsCount = workingEntry.non_editors_count;
// Track membership count changes as well.
if ( oldEditorsCount !== newEditorsCount || oldNonEditorsCount !== newNonEditorsCount ) {
oldMembershipInfos["oldEditorsCount"] = oldEditorsCount;
oldMembershipInfos["oldNonEditorsCount"] = oldNonEditorsCount;
}
/** Quickly check if group contacts have changed and log those first. */
if ( oldGroupContact1 !== newGroupContact1 && oldGroupContact2 !== newGroupContact2 ) {
oldMembershipInfos["oldGroupContact1"] = oldGroupContact1;
oldMembershipInfos["oldGroupContact2"] = oldGroupContact2;
} else if ( oldGroupContact1 !== newGroupContact1 && oldGroupContact2 === newGroupContact2 ) {
oldMembershipInfos["oldGroupContact1"] = oldGroupContact1;
} else if ( oldGroupContact1 === newGroupContact1 && oldGroupContact2 !== newGroupContact2 ) {
oldMembershipInfos["oldGroupContact2"] = oldGroupContact2
}
membershipObj = {
unique_id: Math.random().toString( 36 ).substring( 2 ),
group_name: workingEntry.group_name,
group_contact1: oldMembershipInfos["oldGroupContact1"] ?
oldMembershipInfos["oldGroupContact1"] : oldGroupContact1,
group_contact2: oldMembershipInfos["oldGroupContact2"] ?
oldMembershipInfos["oldGroupContact2"] : oldGroupContact2,
editors_count: oldMembershipInfos["oldEditorsCount"] ?
oldMembershipInfos["oldEditorsCount"] : oldEditorsCount,
non_editors_count: oldMembershipInfos["oldNonEditorsCount"] ?
oldMembershipInfos["oldNonEditorsCount"] : oldNonEditorsCount,
dos_stamp: new Date().toISOString()
};
membershipInfosManifest.push( membershipObj );
// Re-generate the group contacts Lua table based on `membershipInfosManifest`
insertInPlaceGC = 'return {\n';
for ( j = 0; j < membershipInfosManifest.length; j++ ) {
insertInPlaceGC += '\t{\n';
if ( membershipInfosManifest[ j ].unique_id ) {
insertInPlaceGC += generateKeyValuePair(
'unique_id',
membershipInfosManifest[ j ].unique_id
);
}
if ( membershipInfosManifest[ j ].group_name ){
insertInPlaceGC += generateKeyValuePair(
'group_name',
membershipInfosManifest[ j ].group_name
);
}
if ( typeof membershipInfosManifest[ j ].group_contact1 !== 'undefined' &&
membershipInfosManifest[ j ].group_contact1.indexOf( "User:" ) === -1
) {
insertInPlaceGC += generateKeyValuePair(
'group_contact1',
'User:' + membershipInfosManifest[ j ].group_contact1
);
} else if ( typeof membershipInfosManifest[ j ].group_contact1 !== 'undefined' &&
membershipInfosManifest[ j ].group_contact1
) {
insertInPlaceGC += generateKeyValuePair(
'group_contact1',
membershipInfosManifest[ j ].group_contact1
);
} else {
insertInPlaceGC += generateKeyValuePair(
'group_contact1',
''
);
}
if ( typeof membershipInfosManifest[ j ].group_contact2 !== 'undefined' &&
membershipInfosManifest[ j ].group_contact2.indexOf( "User:" ) === -1
) {
insertInPlaceGC += generateKeyValuePair(
'group_contact2',
'User:' + membershipInfosManifest[ j ].group_contact2
);
} else if ( typeof membershipInfosManifest[ j ].group_contact2 !== 'undefined' &&
membershipInfosManifest[ j ].group_contact2
) {
insertInPlaceGC += generateKeyValuePair(
'group_contact2',
membershipInfosManifest[ j ].group_contact2
);
} else {
insertInPlaceGC += generateKeyValuePair(
'group_contact2',
''
);
}
if ( membershipInfosManifest[ j ].editors_count ) {
insertInPlaceGC += generateKeyValuePair(
'editors_count',
membershipInfosManifest[ j ].editors_count
);
}
if ( membershipInfosManifest[ j ].non_editors_count ) {
insertInPlaceGC += generateKeyValuePair(
'non_editors_count',
membershipInfosManifest[ j ].non_editors_count
);
}
if ( membershipInfosManifest[ j ].dos_stamp ) {
insertInPlaceGC += generateKeyValuePair(
'dos_stamp',
membershipInfosManifest[ j ].dos_stamp
);
}
insertInPlaceGC += '\t},\n';
}
insertInPlaceGC += '}';
workingEntry = processWorkingEntry( workingEntry );
editSummary = gadgetMsg[ 'updated-org-info' ] + ' ' + workingEntry.group_name;
}
if ( workingEntry.unique_id !== dialog.uniqueId || !deleteFlag ) {
manifest.push( workingEntry );
}
}
// No unique ID means this is a new entry
if ( !dialog.uniqueId ) {
workingEntry = {
unique_id: Math.random().toString( 36 ).substring( 2 )
};
workingEntry = processWorkingEntry( workingEntry );
editSummary = gadgetMsg[ 'added-new-org-info' ] + ' ' + workingEntry.group_name;
manifest.push( workingEntry );
}
// Re-generate the Lua table based on `manifest`
insertInPlace = 'return {\n';
for ( i = 0; i < manifest.length; i++ ) {
// Keep a list copy of the affiliate name
// Make sure the list is only for recognized affiliates
if ( manifest[ i ].recognition_status === 'recognised' ) {
mrl_affiliates += manifest[ i ].group_name + ',\n';
}
insertInPlace += '\t{\n';
if ( manifest[ i ].unique_id ) {
insertInPlace += generateKeyValuePair(
'unique_id',
manifest[ i ].unique_id
);
}
if ( manifest[ i ].affiliate_code ){
insertInPlace += generateKeyValuePair(
'affiliate_code',
manifest[ i ].affiliate_code
);
}
if ( manifest[ i ].group_name ) {
insertInPlace += generateKeyValuePair(
'group_name',
manifest[ i ].group_name
);
}
if ( manifest[ i ].org_type ) {
insertInPlace += generateKeyValuePair(
'org_type',
manifest[ i ].org_type
);
}
if ( manifest[ i ].region ) {
insertInPlace += generateKeyValuePair(
'region',
manifest[ i ].region
);
}
if ( manifest[ i ].group_country ) {
insertInPlace += generateKeyValuePair(
'group_country',
manifest[ i ].group_country
);
}
if ( !manifest[ i ].legal_entity && manifest[ i ].org_type === 'User Group' ) {
insertInPlace += generateKeyValuePair(
'legal_entity',
'No'
);
} else if ( manifest[ i ].legal_entity && manifest[ i ].org_type === 'User Group' ) {
insertInPlace += generateKeyValuePair(
'legal_entity',
manifest[ i ].legal_entity
);
} else {
insertInPlace += generateKeyValuePair(
'legal_entity',
'Yes'
);
}
if ( manifest[ i ].mission_changed ) {
insertInPlace += generateKeyValuePair(
'mission_changed',
manifest[ i ].mission_changed
);
}
if ( manifest[ i ].explanation ) {
insertInPlace += generateKeyValuePair(
'explanation',
manifest[ i ].explanation
);
}
if ( manifest[ i ].group_page ) {
insertInPlace += generateKeyValuePair(
'group_page',
manifest[ i ].group_page.trim()
);
}
if ( manifest[ i ].member_count ) {
insertInPlace += generateKeyValuePair(
'member_count',
manifest[ i ].member_count
);
}
if ( manifest[ i ].non_editors_count ) {
insertInPlace += generateKeyValuePair(
'non_editors_count',
manifest[ i ].non_editors_count
);
}
if ( manifest[ i ].facebook ) {
insertInPlace += generateKeyValuePair(
'facebook',
manifest[ i ].facebook.trim()
);
}
if ( manifest[ i ].twitter ) {
insertInPlace += generateKeyValuePair(
'twitter',
manifest[ i ].twitter.trim()
);
}
if ( manifest[ i ].other ) {
insertInPlace += generateKeyValuePair(
'other',
manifest[ i ].other.trim()
);
}
if ( manifest[ i ].dm_structure ) {
insertInPlace += generateKeyValuePair(
'dm_structure',
manifest[ i ].dm_structure
);
}
if ( typeof manifest[ i ].group_contact1 !== 'undefined' && manifest[ i ].group_contact1.indexOf( "User:" ) !== -1 ) {
insertInPlace += generateKeyValuePair(
'group_contact1',
manifest[ i ].group_contact1
);
} else if ( manifest[ i ].group_contact1 ) {
insertInPlace += generateKeyValuePair(
'group_contact1',
'User:' + manifest[ i ].group_contact1
);
} else {
insertInPlace += generateKeyValuePair(
'group_contact1',
''
);
}
if ( typeof manifest[ i ].group_contact2 !== 'undefined' && manifest[ i ].group_contact2.indexOf( "User:" ) !== -1 ) {
insertInPlace += generateKeyValuePair(
'group_contact2',
manifest[ i ].group_contact2
);
} else if ( manifest[ i ].group_contact2 ) {
insertInPlace += generateKeyValuePair(
'group_contact2',
'User:' + manifest[ i ].group_contact2
);
} else {
insertInPlace += generateKeyValuePair(
'group_contact2',
''
);
}
if ( manifest[ i ].board_contacts ) {
insertInPlace += generateKeyValuePair(
'board_contacts',
manifest[ i ].board_contacts
);
}
if ( manifest[ i ].agreement_date ){
insertInPlace += generateKeyValuePair(
'agreement_date',
manifest[ i ].agreement_date
);
}
if ( manifest[ i ].fiscal_year_start ){
insertInPlace += generateKeyValuePair(
'fiscal_year_start',
manifest[ i ].fiscal_year_start
);
} else {
insertInPlace += generateKeyValuePair(
'fiscal_year_start',
''
);
}
if ( manifest[ i ].fiscal_year_end ){
insertInPlace += generateKeyValuePair(
'fiscal_year_end',
manifest[ i ].fiscal_year_end
);
} else {
insertInPlace += generateKeyValuePair(
'fiscal_year_end',
''
);
}
if ( manifest[ i ].uptodate_reporting ){
insertInPlace += generateKeyValuePair(
'uptodate_reporting',
manifest[ i ].uptodate_reporting
);
}
if ( manifest[ i ].notes_on_reporting ){
insertInPlace += generateKeyValuePair(
'notes_on_reporting',
manifest[ i ].notes_on_reporting
);
} else {
insertInPlace += generateKeyValuePair(
'notes_on_reporting',
''
);
}
if ( manifest[ i ].recognition_status ){
insertInPlace += generateKeyValuePair(
'recognition_status',
manifest[ i ].recognition_status
);
}
if ( manifest[i].me_bypass_ooc_autochecks ) {
insertInPlace += generateKeyValuePair(
'me_bypass_ooc_autochecks',
manifest[ i ].me_bypass_ooc_autochecks
);
}
if ( manifest[ i ].out_of_compliance_level ){
insertInPlace += generateKeyValuePair(
'out_of_compliance_level',
manifest[ i ].out_of_compliance_level
);
}
if ( manifest[i].reporting_due_date ) {
insertInPlace += generateKeyValuePair(
'reporting_due_date',
manifest[i].reporting_due_date
);
} else { // Fallback to the same day a year ahead for new affiliates.
insertInPlace += generateKeyValuePair(
'reporting_due_date',
getNextReportingDate()
);
}
if ( manifest[ i ].derecognition_date ){
insertInPlace += generateKeyValuePair(
'derecognition_date',
manifest[ i ].derecognition_date
);
}
if ( manifest[ i ].derecognition_note ){
insertInPlace += generateKeyValuePair(
'derecognition_note',
manifest[ i ].derecognition_note
);
}
if ( manifest[ i ].dos_stamp ) {
insertInPlace += generateKeyValuePair(
'dos_stamp',
manifest[ i ].dos_stamp
);
}
insertInPlace += '\t},\n';
}
insertInPlace += '}';
// Make changes to the Org Info table as required.
new mw.Api().postWithToken(
'csrf',
{
action: 'edit',
bot: true,
nocreate: true,
summary: editSummary,
pageid: 10603224, // [[Module:Organizational_Informations]]
text: insertInPlace,
contentmodel: 'Scribunto'
}
).then( function () {
dialog.close();
new mw.Api().postWithToken(
'csrf',
{
action: 'edit',
bot: true,
nocreate: true,
summary: 'Log changes to new affiliate contacts',
pageid: 11620639, // [[Module:Organizational_Informations/Membership_Infos]]
text: insertInPlaceGC,
contentmodel: 'Scribunto'
}
).then( function () {
/** After saving, show a message box */
var messageDialog = new OO.ui.MessageDialog();
var windowManager = new OO.ui.WindowManager();
$( 'body' ).append( windowManager.$element );
// Add the dialog to the window manager.
windowManager.addWindows( [ messageDialog ] );
// Configure the message dialog when it is opened with the window manager's openWindow() method.
windowManager.openWindow( messageDialog, {
title: gadgetMsg[ 'success-message' ],
message: gadgetMsg[ 'org-info-saved' ],
actions: [
{
action: 'accept',
label: 'Dismiss',
flags: 'primary'
}
]
});
// Purge the cache of the page from which the edit was made
new mw.Api().postWithToken(
'csrf',
{ action: 'purge', titles: mw.config.values.wgPageName }
).then( function () {
// Defer reconstruction MRL of affiliates to background.
new mw.Api().postWithToken(
'csrf',
{
action: 'edit',
bot: true,
nocreate: true,
summary: 'Reconstructed MRL of affiliates for all affiliates in the system.',
pageid: 11608672, // [[WADP/MRL/List Of All Wikimedia Affiliates]]
text: mrl_affiliates,
contentmodel: 'wikitext'
}
);
location.reload();
} );
} );
} ).catch( function ( error ) {
alert( gadgetMsg[ 'failed-to-save-to-lua-table' ] );
dialog.close();
console.error( error );
} );
} );
} );
};
// Edit content via the form
$( '.record_id' ).each( function () {
var $icon = $( this ),
editButton;
editButton = new OO.ui.ButtonWidget( {
framed: false,
label: 'update',
icon: 'edit',
flags: [ 'progressive' ]
} ).on( 'click', function () {
// First check if the user is logged in
if ( mw.config.get ( 'wgUserName' ) === null ) {
alert( gadgetMsg[ 'you-need-to-log-in' ] );
} else {
new mw.Api().get( getModuleContent( 'Organizational_Informations' ) ).then( function ( data ) {
var entryData, record;
record = editButton.$element
.closest( '.record' )
.data( 'record-unique-id' );
entryData = cleanRawEntry(
getRelevantRawEntry(
parseContentModule( data.query.pages ),
record
)
);
openWindow( entryData );
} );
}
} );
$icon.append( editButton.$element );
} );
/**
* The dialog / window to be displayed as editor when
* when updating the records or table entries.
*
* @param {Object} config
*/
openWindow = function ( config ) {
var orginfoEditor;
config.size = 'large';
orginfoEditor = new OrgInfoEditor( config );
windowManager = new OO.ui.WindowManager();
$( 'body' ).append( windowManager.$element );
windowManager.addWindows( [ orginfoEditor ] );
windowManager.openWindow( orginfoEditor );
};
/**
* Open up a dialog when a new entry is to be submitted
*/
$( '.orgInfo' ).on( 'click', function () {
if ( users.indexOf( mw.config.values.wgUserName ) > -1 ) {
openWindow( {} );
} else {
alert( gadgetMsg[ 'me-staffs-only' ] );
}
} );
}
// This is called after module dependencies are ready
function initAfterModules() {
new mw.Api().get( {
action: 'query',
list: 'messagecollection',
mcgroup: 'page-Template:I18n/Reports',
mclanguage: userLang
} ).then( function ( data ) {
var i, res, key, val;
res = data.query.messagecollection;
for ( i = 0; i < res.length; i++ ) {
key = res[ i ].key.replace( 'Template:I18n/Reports/', '' );
val = res[ i ].translation;
if ( !val ) {
// No translation; fall back to English
val = res[ i ].definition;
}
gadgetMsg[ key ] = val;
}
initAfterMessages();
} ).catch( function ( error ) {
console.error( error, 'Unable to load translation strings - __OIF__' );
} );
}
mw.loader.using( [
'mediawiki.api',
'oojs-ui',
'oojs-ui-core',
'oojs-ui.styles.icons-editing-core',
'ext.gadget.luaparse',
'mediawiki.widgets.DateInputWidget'
] ).then( initAfterModules );
}() );