Utente:Ricordisamoa/PDC.js
Questa pagina definisce alcuni parametri di aspetto e comportamento generale di tutte le pagine. Per personalizzarli vedi Aiuto:Stile utente.
Nota: dopo aver salvato è necessario pulire la cache del proprio browser per vedere i cambiamenti (per le pagine globali è comunque necessario attendere qualche minuto). Per Mozilla / Firefox / Safari: fare clic su Ricarica tenendo premuto il tasto delle maiuscole, oppure premere Ctrl-F5 o Ctrl-R (Command-R su Mac); per Chrome: premere Ctrl-Shift-R (Command-Shift-R su un Mac); per Konqueror: premere il pulsante Ricarica o il tasto F5; per Opera può essere necessario svuotare completamente la cache dal menù Strumenti → Preferenze; per Internet Explorer: mantenere premuto il tasto Ctrl mentre si preme il pulsante Aggiorna o premere Ctrl-F5.
// <nowiki>
/* eslint-env browser, jquery */
/* global mediaWiki, OO */
( function ( mw, $ ) {
'use strict';
var namespaces, AssessmentsHistoryEditor, VoteCounter, PdcAgent, PDC, VoteButtons,
ProgressHandler,
AllCategoriesLookupWidget, PdcDialog, PublicButtons, SysopButtons;
namespaces = mw.config.get( 'wgFormattedNamespaces' );
/**
* @class AssessmentsHistoryEditor
*
* @constructor
*/
AssessmentsHistoryEditor = function () {
this.titoloTemplate = 'Cronologia valutazioni';
this.regex = /(\{\{\s*(?:[Cc]ronologia[_ ]valutazioni|[Pp]rocedure|[Vv]alutazioni)\s*)([\S\s]*?)\}\}/;
};
/**
* Restituisce dei parametri numerati.
*
* @private
* @param {Object} parametri - I parametri non numerati
* @param {number} numero - Il numero da aggiungere ai nomi dei parametri
* @return {string}
*/
AssessmentsHistoryEditor.prototype.ottieniParametriNumerati = function ( parametri, numero ) {
return $.map( parametri, function ( value, key ) {
return key + numero + '=' + value;
} ).join( '|' );
};
/**
* Restituisce il massimo numero utilizzato da una serie di parametri numerati.
*
* @private
* @param {string[]} parametri
* @return {number}
*/
AssessmentsHistoryEditor.prototype.ottieniMassimoNumeroParametri = function ( parametri ) {
var max, paramIndex, m, num;
max = 0;
for ( paramIndex = 0; paramIndex < parametri.length; paramIndex++ ) {
m = parametri[ paramIndex ].match( /^\s*[A-Za-z]+(\d+)\s*\=/ );
if ( m !== null ) {
num = parseInt( m[ 1 ], 10 );
if ( num.toString() === m[ 1 ] && num > max ) {
max = num;
}
}
}
return max;
};
/**
* Aggiunge dei parametri a un template Cronologia valutazioni, eventualmente creandolo.
*
* @param {string} testo - Il contenuto della pagina
* @param {Object} parametri - I parametri da aggiungere al template, non numerati
* @return {string}
*/
AssessmentsHistoryEditor.prototype.aggiungiParametri = function ( testo, parametri ) {
var match, newText, start, max;
match = this.regex.exec( testo );
if ( match === null ) {
// TODO: inserire sotto ai template {{Progetti interessati}} e {{Tradotto da}} qualora presenti
newText =
'{{' + this.titoloTemplate + '\n' +
'|' + this.ottieniParametriNumerati( parametri, 1 ) + '\n' +
'}}' +
( testo !== '' && testo[ 0 ] !== '\n' ? '\n' : '' ) + // A capo solo se necessario
testo;
} else {
start = match.index + match[ 1 ].length + match[ 2 ].length;
newText = testo.slice( 0, start );
if ( newText[ newText.length - 1 ] !== '\n' ) {
newText += '\n';
}
max = this.ottieniMassimoNumeroParametri( match[ 2 ].split( '|' ) );
newText += '|' + this.ottieniParametriNumerati( parametri, max + 1 ) + '\n';
newText += testo.slice( start );
}
return newText;
};
/**
* @class VoteCounter
*
* @constructor
* @param {Object} config - Opzioni di configurazione
* @cfg {jQuery} $content
* @cfg {string} pageName
* @cfg {string[]} voteNullItems
* @cfg {Object} voteSections
*/
VoteCounter = function ( config ) {
this.$content = config.$content;
this.pageName = config.pageName;
this.voteNullItems = config.voteNullItems;
this.voteSections = config.voteSections;
};
/**
* Restituisce il numero della sezione a cui si riferisce un collegamento di modifica sezione.
*
* @private
* @param {HTMLAnchorElement} link - Il collegamento di modifica sezione
* @return {string|undefined}
*/
VoteCounter.prototype.mapEditSectionLinks = function ( link ) {
var linkUri;
// Skip every URI that mw.Uri cannot parse
try {
linkUri = new mw.Uri( link.href );
} catch ( e ) {
return;
}
if (
linkUri.host === window.location.hostname &&
linkUri.query !== undefined &&
linkUri.query.section !== undefined &&
linkUri.query.title === this.pageName &&
linkUri.query.action === 'edit'
) {
return linkUri.query.section;
}
};
/**
* Restituisce le sezioni di votazione della procedura di cancellazione.
*
* @return {Object}
*/
VoteCounter.prototype.getSections = function () {
var self = this,
sections = {};
self.$content.find( '.mw-headline' ).each( function () {
var sectionNums,
$this = $( this ),
sectionId = $this.attr( 'id' ),
voteIcon = self.voteSections[ sectionId ];
if ( voteIcon === undefined ) {
return;
}
sectionNums = $this.next( '.mw-editsection' ).find( 'a[href]' )
.map( function ( i, link ) {
return self.mapEditSectionLinks( link );
} )
.get();
if ( sectionNums.length !== 1 ) {
// Absent or non-unique 'edit' link
return;
}
sections[ sectionId ] = {
icon: voteIcon,
num: sectionNums[ 0 ],
votes: $this.parent().next( 'ol' ).find( 'li' ).filter( function () {
return self.voteNullItems.indexOf( this.textContent ) === -1;
} ).length
};
} );
return sections;
};
/**
* @class PdcAgent
*
* @constructor
* @param {Object} config - Configuration options
* @cfg {mw.Api} api - MediaWiki API instance
* @cfg {AssessmentsHistoryEditor} assessmentsHistoryEditor - Assessments history editor
* @cfg {mw.Map} i18n - Language translation
* @cfg {Object} l10n - Site localization
* @cfg {Object} namespaces - Site namespaces
*/
PdcAgent = function ( config ) {
var l10nMsgs;
this.api = config.api;
this.assessmentsHistoryEditor = config.assessmentsHistoryEditor;
this.i18n = config.i18n;
this.config = config.l10n;
this.namespaces = config.namespaces;
l10nMsgs = new mw.Map();
$.each( this.config, function ( key, value ) {
l10nMsgs.set( key, value );
} );
this.l10nMsgs = l10nMsgs;
};
PdcAgent.prototype.msg = function ( nome ) {
var params = Array.prototype.slice.call( arguments, 1 );
return new mw.Message( this.i18n, nome, params ).text();
};
PdcAgent.prototype.l10nMsg = function ( nome ) {
var params = Array.prototype.slice.call( arguments, 1 );
return new mw.Message( this.l10nMsgs, nome, params ).text();
};
/**
* Ottiene un messaggio di errore.
*
* @param {string} messaggio - Il codice corrispondente al messaggio di errore da visualizzare
* @param {Object|string} [dati] - Eventuali dettagli sull'errore
* @return {string}
*/
PdcAgent.prototype.errorMsg = function ( messaggio, dati ) {
messaggio = this.msg( messaggio );
if ( dati ) {
if ( dati.error && dati.error.info ) {
dati = dati.error.info;
}
messaggio = this.msg( 'error-msg', messaggio, dati );
}
return messaggio;
};
/**
* Restituisce il codice HTML per un link alla pagina di un dato utente.
*
* @param {string} nome - Il nome dell'utente
* @return {string}
*/
PdcAgent.prototype.linkUtente = function ( nome ) {
return $( '<a>' )
.attr( 'href', mw.util.getUrl( this.namespaces[ 2 ] + ':' + nome ) )
.text( nome )
.get( 0 ).outerHTML;
};
/**
* Ottiene il titolo della pagina relativa a una procedura di cancellazione.
*
* @param {string} procedura - La procedura di cancellazione
* @return {jQuery.Promise}
*/
PdcAgent.prototype.ottieniTitoloPagina = function ( procedura ) {
var self = this;
return self.ottieniUltimaVersionePagina( procedura, 'content' )
.then( function ( rev ) {
var m;
if ( rev.slots && rev.slots.main ) {
m = ( rev.slots.main.content || '' ).match( self.config.nominationTemplateRegex );
if ( m ) {
return m[ 1 ];
}
}
return $.Deferred().reject();
} );
};
/**
* Verifica i requisiti di apertura delle procedure da parte di un utente.
* vedi [[Wikipedia:Requisiti di voto#Requisiti relativi alle votazioni sulle pagine]]
*
* @param {string} [utente] - Il nome dell'utente del quale verificare i contributi
* @return {jQuery.Promise}
*/
PdcAgent.prototype.verificaRequisiti = function ( utente ) {
var self = this;
if ( utente === undefined ) {
utente = mw.config.get( 'wgUserName' );
}
if ( mw.config.get( 'wgDBname' ) === 'testwiki' ) {
return $.Deferred().resolve( true );
}
return self.api.get( {
action: 'query',
format: 'json',
formatversion: 2,
list: 'users|usercontribs',
usprop: 'editcount',
ususers: utente,
ucuser: utente,
ucprop: 'timestamp',
ucdir: 'newer',
uclimit: 1
} )
.then( function ( data ) {
var user, uc;
if ( !data.query || !data.query.users || data.query.users.length !== 1 ) {
return false;
}
user = data.query.users[ 0 ];
if ( !user.name || user.name !== utente || !user.editcount || user.editcount < self.config.minEdits || !data.query.usercontribs ) {
return false;
}
uc = data.query.usercontribs;
if ( uc.length !== 1 || !uc[ 0 ].user || !uc[ 0 ].timestamp || ( new Date() - new Date( uc[ 0 ].timestamp ) ) / 86400000 < self.config.minDaysOld ) {
return false;
}
return true;
} );
};
/**
* Ottiene un array con tutte le revisioni della pagina,
* come oggetti contenenti l'autore.
*
* @param {string} titolo - Il titolo della pagina
* @return {jQuery.Promise}
*/
PdcAgent.prototype.ottieniContributori = function ( titolo ) {
var self = this,
params = {
action: 'query',
format: 'json',
formatversion: 2,
prop: 'revisions',
titles: titolo,
rvprop: 'user',
rvlimit: 'max'
},
revs = [],
getRevsRecursive = function ( continua ) {
return self.api.get(
$.extend( {}, params, continua || {} )
)
.then( function ( data ) {
var pages = data.query.pages;
if ( pages.length === 1 && pages[ 0 ].revisions ) {
// Aggiunge tutte le revisioni con la proprietà "user"
revs = revs.concat(
$.grep( pages[ 0 ].revisions, function ( e ) {
return e.user !== undefined;
} )
);
}
if ( data[ 'continue' ] ) {
// Ci sono ancora revisioni, si continua
return getRevsRecursive( data[ 'continue' ] );
} else {
// Finito!
return revs;
}
} );
};
return getRevsRecursive();
};
/**
* Ottiene il nome dell'utente registrato con più contributi da una lista di revisioni.
*
* @param {Object[]} contributori - Le revisioni della pagina
* @return {string|null}
*/
PdcAgent.prototype.maggiorContributore = function ( contributori ) {
var ordinati, maggiore,
utenti = {};
$.each( contributori, function ( i, rv ) {
if ( rv.anon === undefined ) {
if ( utenti[ rv.user ] ) {
utenti[ rv.user ] = utenti[ rv.user ] + 1;
} else {
utenti[ rv.user ] = 1;
}
}
} );
ordinati = Object.keys( utenti ).sort( function ( a, b ) {
return utenti[ b ] - utenti[ a ];
} );
maggiore = ordinati[ 0 ] || null;
if ( maggiore !== null ) {
$.each( utenti, function ( nome, contributi ) {
if ( nome !== maggiore && contributi === utenti[ maggiore ] ) {
// Pari merito
maggiore = null;
return false;
}
} );
}
return maggiore;
};
/**
* Aggiunge il template {{Cancellazione}} all'inizio di una pagina.
*
* @param {string} titolo - Il titolo della pagina proposta per la cancellazione
* @param {integer} numero - Il numero della procedura di cancellazione
* @param {string[]} argomenti - Gli eventuali argomenti al quale la pagina è relativa
* @return {jQuery.Promise}
*/
PdcAgent.prototype.aggiungiAvvisoVoce = function ( titolo, numero, argomenti ) {
argomenti = $.map( [ '', '2' ], function ( suf, i ) {
if ( argomenti.length > i ) {
return '|arg' + suf + '=' + argomenti[ i ];
}
} )
.join( '' );
return this.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
summary: this.l10nMsg( 'baseSummary', this.config.nominationNoticeSummary ),
prependtext: '<noinclude>{{' + this.config.nominationNoticeTemplate + argomenti + '}}</noinclude>\n',
nocreate: 1
} );
};
/**
* Rimuove il template {{Cancellazione}} da una pagina.
*
* @param {string} titolo - Il titolo della pagina dalla quale rimuovere l'avviso
* @return {jQuery.Promise}
*/
PdcAgent.prototype.rimuoviAvvisoVoce = function ( titolo ) {
var self = this;
return self.ottieniUltimaVersionePagina( titolo, 'content|timestamp' )
.then( function ( rev ) {
var content, newText;
content = rev.slots.main.content;
newText = content.replace(
self.config.removeNominationNoticeReplace,
self.config.removeNominationNoticeReplaceWith
);
if ( newText === content ) {
// sostituzione fallita
return $.Deferred().reject();
}
return self.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
summary: self.l10nMsg( 'baseSummary', self.config.removeNominationNoticeSummary ),
text: newText,
basetimestamp: rev.timestamp,
nocreate: 1
} );
} );
};
/**
* Restituisce il titolo della pagina di discussione corrispondente a una pagina.
*
* @param {string} titolo - Il titolo della pagina
* @return {string|null}
*/
PdcAgent.prototype.ottieniTitoloDiscussione = function ( titolo ) {
var namespaceId;
titolo = mw.Title.newFromText( titolo );
if ( titolo === null ) {
return null;
}
namespaceId = titolo.getNamespaceId();
if ( namespaceId % 2 !== 0 ) {
return null;
}
titolo = mw.Title.makeTitle( namespaceId + 1, titolo.getMainText() );
if ( titolo === null ) {
return null;
}
return titolo.getPrefixedText();
};
/**
* Aggiorna il template {{Cronologia valutazioni}} nella discussione di una pagina.
*
* @param {string} titolo - Il titolo della pagina valutata
* @param {Object} parametri - I parametri da aggiungere al template, non numerati
* @return {jQuery.Promise}
*/
PdcAgent.prototype.aggiornaCronologiaValutazioni = function ( titolo, parametri ) {
var fallback,
self = this;
titolo = self.ottieniTitoloDiscussione( titolo );
if ( titolo === null ) {
return $.Deferred().reject();
}
parametri = $.extend( {}, self.config.assessmentsHistoryDefaultParams, parametri );
fallback = {
content: ''
};
return self.ottieniUltimaVersionePagina( titolo, 'content|timestamp', fallback )
.then( function ( rev ) {
var content, newText, params;
content = rev.slots.main.content;
newText = self.assessmentsHistoryEditor.aggiungiParametri( content, parametri );
if ( newText === undefined || newText === content ) {
// modifica non riuscita
return $.Deferred().reject();
}
params = {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
summary: self.l10nMsg( 'baseSummary', self.config.assessmentsHistoryUpdateSummary ),
text: newText
};
if ( rev === fallback ) {
// Pagina nuova
params.createonly = true;
} else {
// Pagina esistente
params.basetimestamp = rev.timestamp;
params.nocreate = true;
}
return self.api.postWithToken( 'csrf', params );
} );
};
/**
* Aggiunge il template {{Cancellazione}} in una nuova sezione di una o più pagine di discussione.
*
* @param {string} titolo - Il titolo della pagina da proporre per la cancellazione
* @param {number} numero - Il numero della procedura di cancellazione
* @param {string[]} discussioni - I titoli delle pagine di discussione degli utenti o dei progetti da avvisare
* @return {jQuery.Promise}
*/
PdcAgent.prototype.notificaProcedura = function ( titolo, numero, discussioni ) {
var self = this,
deferreds = [],
sectionTitle = self.l10nMsg( 'notificationNewSectionTitle', titolo ),
args = ( numero === 1 ? '' : ( '|' + numero ) ),
sectionContent = '{{' + self.config.notificationNewSectionTemplate + '|' + titolo + args + '}}--~~~~';
$.each( discussioni, function ( i, discussione ) {
deferreds.push(
self.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: discussione,
section: 'new',
summary: sectionTitle,
text: sectionContent
} )
.done( function () {
console.info( self.msg( 'notify-done', discussione ) );
} )
);
} );
return $.when.apply( $, deferreds );
};
/**
* Controlla l'esistenza di una pagina.
*
* @param {string} titolo - Il titolo della pagina
* @return {jQuery.Promise}
*/
PdcAgent.prototype.controllaEsistenzaPagina = function ( titolo ) {
return this.api.get( {
action: 'query',
format: 'json',
formatversion: 2,
titles: titolo
} )
.then( function ( data ) {
if ( data && data.query && data.query.pages && data.query.pages.length === 1 ) {
return data.query.pages[ 0 ].missing !== true;
}
return $.Deferred().reject();
} );
};
/**
* Ottiene il primo numero disponibile per una procedura di cancellazione.
*
* @param {string} titolo - Il titolo della pagina da proporre per la cancellazione
* @param {number} [numero=1] - Il numero da cui iniziare
* @return {jQuery.Promise}
*/
PdcAgent.prototype.ottieniNumeroDisponibile = function ( titolo, numero ) {
var procedura,
self = this;
if ( numero === undefined ) {
numero = 1;
}
procedura = self.config.base + '/' + titolo + ( numero !== 1 ? '/' + numero : '' );
return self.controllaEsistenzaPagina( procedura )
.then( function ( exists ) {
if ( exists ) {
return self.ottieniNumeroDisponibile( titolo, numero + 1 );
}
return $.Deferred().resolve( procedura, numero );
} );
};
/**
* Crea una procedura di cancellazione dal titolo della pagina da cancellare.
*
* @param {string} titolo - Il titolo della pagina da proporre per la cancellazione
* @param {string} motivazione - La motivazione per la quale proporre la cancellazione della pagina
* @return {jQuery.Promise}
*/
PdcAgent.prototype.creaProceduraDaPagina = function ( titolo, motivazione ) {
var self = this;
return self.ottieniNumeroDisponibile( titolo )
.then( function ( procedura, numero ) {
return self.creaProcedura( procedura, motivazione )
.then( function () {
return $.Deferred().resolve( procedura, numero );
} );
} );
};
/**
* Crea una procedura di cancellazione dal titolo della procedura.
*
* @param {string} procedura - Il titolo della procedura di cancellazione
* @param {string} motivazione - La motivazione per la quale proporre la cancellazione della pagina
* @return {jQuery.Promise}
*/
PdcAgent.prototype.creaProcedura = function ( procedura, motivazione ) {
return this.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: procedura,
summary: this.l10nMsg( 'baseSummary', this.config.newNominationSummary ),
text: '{{' + this.config.newNominationTemplate + '}}\n\n' + motivazione + ' --~~~~',
createonly: 1
} );
};
/**
* Ottiene la versione più recente di una pagina.
*
* @param {string} titolo - Il titolo della pagina
* @param {string|string[]} rvprop - Le proprietà da ottenere
* @param {Mixed} [fallback] - Il valore da utilizzare in caso di pagina mancante
* @return {jQuery.Promise}
*/
PdcAgent.prototype.ottieniUltimaVersionePagina = function ( titolo, rvprop, fallback ) {
return this.api.get( {
action: 'query',
format: 'json',
formatversion: 2,
titles: titolo,
prop: 'revisions',
rvprop: rvprop,
rvslots: 'main',
rvlimit: 1
} )
.then( function ( data ) {
var deferred = $.Deferred();
if (
data &&
data.query &&
data.query.pages &&
data.query.pages.length === 1
) {
if ( data.query.pages[ 0 ].missing === true && fallback !== undefined ) {
return deferred.resolve( fallback );
}
if (
data.query.pages[ 0 ].revisions &&
data.query.pages[ 0 ].revisions.length === 1
) {
return deferred.resolve( data.query.pages[ 0 ].revisions[ 0 ] );
}
}
return deferred.reject();
} );
};
/**
* Annulla una procedura di cancellazione.
*
* @param {string} titolo - Il titolo della procedura da annullare
* @param {string} motivazione - La motivazione per la quale la procedura va annullata
* @return {jQuery.Promise}
*/
PdcAgent.prototype.annullaProcedura = function ( titolo, motivazione ) {
var self = this;
return self.ottieniUltimaVersionePagina( titolo, 'content|timestamp' )
.then( function ( rev ) {
var content, newText;
content = rev.slots.main.content;
newText = content.replace(
self.config.cancelledReplace,
self.config.cancelledReplaceWith
);
if ( newText === content ) {
// sostituzione fallita
return $.Deferred().reject();
}
newText += '\n\n{{' + self.config.cancelledTemplate + '}} ' + motivazione.trim() + ' --~~~~';
return self.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
summary: self.l10nMsg( 'baseSummary', self.config.cancelledSummary ),
text: newText,
basetimestamp: rev.timestamp,
nocreate: 1
} );
} );
};
/**
* Passa alla modalità consensuale.
*
* @param {string} titolo - Il titolo della procedura di cancellazione (già esistente)
* @param {string} motivazione - La motivazione per la quale l'utente intende opporsi alla cancellazione tacita della pagina
* @return {jQuery.Promise}
*/
PdcAgent.prototype.consensuale = function ( titolo, motivazione ) {
return this.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
summary: this.l10nMsg( 'baseSummary', this.config.consensualeStartSummary ),
appendtext: '\n\n{{' + this.config.consensualeStartTemplate + '}}\n\n' +
motivazione.trim() + ' --~~~~',
nocreate: 1
} );
};
/**
* Proroga una procedura di cancellazione
*
* @param {string} titolo - Il titolo della procedura di cancellazione (già esistente)
* @param {integer} giorni - Il numero di giorni per i quali prorogare la procedura
* @return {jQuery.Promise}
*/
PdcAgent.prototype.prorogaProcedura = function ( titolo, giorni ) {
var giorniArg;
if ( giorni === this.config.deferDefaultDays ) {
giorniArg = '';
} else {
giorniArg = '|' + giorni;
}
return this.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
summary: this.l10nMsg( 'baseSummary', this.l10nMsg( 'deferStartSummary', giorni ) ),
appendtext: '\n\n{{' + this.config.deferStartTemplate + giorniArg + '}}',
nocreate: 1
} );
};
/**
* Per gli amministratori: passa alla modalità votazione.
*
* @param {string} titolo - Il titolo della procedura di cancellazione (già esistente)
* @return {jQuery.Promise}
*/
PdcAgent.prototype.avviaVotazione = function ( titolo ) {
return this.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
summary: this.l10nMsg( 'baseSummary', this.config.voteStartSummary ),
appendtext: '\n\n{{' + this.config.voteStartTemplate + '}}',
nocreate: 1
} );
};
/**
* Vota a favore o contro la cancellazione di una pagina.
*
* @param {string} titolo - Il titolo della procedura di cancellazione (già esistente)
* @param {integer|string} numeroSezione - Il numero della sezione in cui votare
* @param {string} motivazione - La motivazione (facoltativa) per il voto espresso
* @return {jQuery.Promise}
*/
PdcAgent.prototype.vota = function ( titolo, numeroSezione, motivazione ) {
motivazione = motivazione.trim();
return this.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
section: numeroSezione,
summary: this.l10nMsg( 'baseSummary', this.config.voteSummary ),
appendtext: '\n# ' + motivazione + ( motivazione !== '' ? ' ' : '' ) + '--~~~~',
nocreate: 1
} );
};
/**
* Controlla se una pagina contiene già un avviso di cancellazione.
*
* @param {string} titolo - Il titolo della pagina da controllare
* @return {jQuery.Promise}
*/
PdcAgent.prototype.inCancellazione = function ( titolo ) {
return this.api.get( {
action: 'query',
format: 'json',
formatversion: 2,
titles: titolo,
prop: 'templates',
tltemplates: this.config.baseTemplate
} )
.then( function ( data ) {
return (
data.query &&
data.query.pages &&
data.query.pages.length === 1 &&
( data.query.pages[ 0 ].templates || [] ).length === 1
);
} );
};
/**
* Controlla lo stato di una procedura di cancellazione.
*
* @param {string} titolo - Il titolo della procedura da controllare
* @return {jQuery.Promise}
*/
PdcAgent.prototype.ottieniStatoProcedura = function ( titolo ) {
return this.api.get( {
action: 'query',
format: 'json',
formatversion: 2,
titles: titolo,
prop: 'categories|revisions',
rvprop: 'timestamp|user',
cllimit: 'max',
rvdir: 'newer',
rvlimit: 1
} )
.then( function ( data ) {
var stato, page;
if (
data === undefined ||
data.query === undefined ||
data.query.pages === undefined ||
data.query.pages.length !== 1
) {
return $.Deferred().reject();
}
page = data.query.pages[ 0 ];
if ( page.missing === true || page.title === undefined ) {
return $.Deferred().reject();
}
stato = {
procedura: page.title
};
$.each( page.categories || [], function () {
var inizio, consensuale, prorogata, votazione;
if ( this.title === 'Categoria:Procedure di cancellazione in corso' ) {
stato.terminata = false;
} else if ( this.title === 'Categoria:Procedure di cancellazione protette' ) {
stato.terminata = true;
}
inizio = this.title.match( /^Categoria\:Cancellazioni del (\d\d? .+ \d{4})$/ );
consensuale = this.title.match( /^Categoria\:Cancellazioni consensuali del (\d\d? .+ \d{4})$/ );
prorogata = this.title.match( /^Categoria\:Cancellazioni consensuali prorogate del (\d\d? .+ \d{4})$/ );
votazione = this.title.match( /^Categoria\:Cancellazioni con votazione del (\d\d? .+ \d{4})$/ );
if ( inizio ) {
stato.inizio = inizio[ 1 ];
}
if ( consensuale ) {
stato.consensuale = consensuale[ 1 ];
}
if ( prorogata ) {
stato.prorogata = prorogata[ 1 ];
}
if ( votazione ) {
stato.votazione = votazione[ 1 ];
}
} );
if ( page.revisions && page.revisions.length === 1 ) {
stato.creazione = page.revisions[ 0 ];
}
return stato;
} );
};
/**
* Per gli amministratori: protegge la procedura di cancellazione.
*
* @param {string} titolo - Il titolo della procedura da proteggere
* @return {jQuery.Promise}
*/
PdcAgent.prototype.proteggiPagina = function ( titolo ) {
return this.api.postWithToken( 'csrf', {
action: 'protect',
format: 'json',
formatversion: 2,
title: titolo,
protections: this.config.protectLevel,
reason: this.l10nMsg( 'baseSummary', this.config.protectReason )
} );
};
/**
* Per gli amministratori: cancella una pagina.
*
* @param {string} titolo - Il titolo della pagina da cancellare
* @param {string} motivazione - La motivazione della cancellazione
* @return {jQuery.Promise}
*/
PdcAgent.prototype.cancellaPagina = function ( titolo, motivazione ) {
return this.api.postWithToken( 'csrf', {
action: 'delete',
format: 'json',
formatversion: 2,
title: titolo,
reason: this.l10nMsg( 'baseSummary', motivazione )
} );
};
/**
* Per gli amministratori: termina una procedura di cancellazione.
*
* @param {string} titolo - Il titolo della procedura di cancellazione (terminata)
* @param {string} esito - L'esito della procedura di cancellazione: "Deleted" o "Kept"
* @param {string} modalità - La modalità della procedura di cancellazione
* @return {jQuery.Promise}
*/
PdcAgent.prototype.terminaProcedura = function ( titolo, esito, modalità ) {
if ( [ 'Deleted', 'Kept' ].indexOf( esito ) === -1 ) {
return $.Deferred().reject();
}
return this.api.postWithToken( 'csrf', {
action: 'edit',
format: 'json',
formatversion: 2,
title: titolo,
// simpleDeletedTemplate, consensualeDeletedTemplate, votazioneDeletedTemplate,
// consensualeKeptTemplate, votazioneKeptTemplate
appendtext: this.l10nMsg( modalità + esito + 'Template' ),
// simpleDeletedSummary, consensualeDeletedSummary, votazioneDeletedSummary,
// consensualeKeptSummary, votazioneKeptSummary
summary: this.l10nMsg( 'baseSummary', this.config[ modalità + esito + 'Summary' ] ),
nocreate: 1
} );
};
/**
* Purga la cache del server relativa a una pagina, compresa la cache dei link (utile per le categorie).
*
* @param {string} titolo - Il titolo della pagina da purgare
* @return {jQuery.Promise}
*/
PdcAgent.prototype.purgaPagina = function ( titolo ) {
return this.api.post( {
action: 'purge',
format: 'json',
formatversion: 2,
forcelinkupdate: 1,
titles: titolo
} );
};
PDC = {
api: new mw.Api( {
ajax: {
headers: {
'Api-User-Agent': 'PDC.js (https://it.wiki.x.io/wiki/Utente:Ricordisamoa/PDC.js)'
}
}
} ),
namespaces: namespaces,
dependencies: {
/**
* Moduli ResourceLoader da cui dipende lo script.
*/
general: [
'mediawiki.jqueryMsg',
'mediawiki.api',
'mediawiki.Title',
'oojs-ui-widgets'
],
/**
* Moduli ResourceLoader da cui dipende la funzionalità della finestra di dialogo.
*/
dialog: [
'oojs-ui-windows'
]
},
/**
* Configurazione per Wikipedia in italiano.
*/
config: {
baseSummary: '[[' + namespaces[ 2 ] + ':Ricordisamoa/PDC.js|PDC.js]]: $1',
base: namespaces[ 4 ] + ':Pagine da cancellare',
help: namespaces[ 4 ] + ':Regole per la cancellazione',
baseTemplate: namespaces[ 10 ] + ':Cancellazione',
actInNamespaces: [ 0 ],
afdCatPrefix: 'Pagine in cancellazione - ',
wikiprojectNamespace: 102,
autoRfd: [
[ 'non enciclopedica, puoi ', 'proporne', ' la ' ]
],
minEdits: 50,
minDaysOld: 30,
minDeferrableDays: 7,
newNominationTemplate: 'subst:Cancellazione/creavvisotesto',
newNominationSummary: 'nuova richiesta di cancellazione',
nominationNoticeTemplate: 'Cancellazione',
nominationNoticeSummary: 'richiesta di cancellazione',
notificationNewSectionTitle: 'Cancellazione [[$1]]',
notificationNewSectionTemplate: 'Cancellazione',
consensualeStartTemplate: 'subst:Consensuale',
consensualeStartSummary: 'avvio della modalità consensuale',
deferMinDays: 1,
deferMaxDays: 7,
deferDefaultDays: 7,
deferStartTemplate: 'subst:Proroga',
deferStartSummary: 'modalità consensuale prorogata per $1 {{PLURAL:$1|giorno|giorni}}',
voteStartTemplate: 'subst:Votazione',
voteStartSummary: 'avvio della votazione',
voteSummary: 'voto',
voteSections: {
Cancellare: '//up.wiki.x.io/wikipedia/commons/thumb/8/89/Symbol_delete_vote.svg/30px-Symbol_delete_vote.svg.png',
Mantenere: '//up.wiki.x.io/wikipedia/commons/thumb/e/e7/Symbol_kept_vote.svg/30px-Symbol_kept_vote.svg.png'
},
voteNullItems: [ '...' ],
getVoteOutcome: function ( sections ) {
// vedi [[Template:Paginecancellare/Criteri]]
return (
sections.Cancellare >= 7 &&
sections.Cancellare >= sections.Mantenere * 2
) ? 'Cancellare' : 'Mantenere';
},
simpleDeletedTemplate: '\n\n{{subst:FineCanc}}--~~~~',
simpleDeletedSummary: 'notifica dell\'avvenuta cancellazione in modalità semplificata',
simpleDeletedReason: 'Come da procedura di [[WP:RPC|cancellazione semplificata]]: [[$1]]',
consensualeDeletedTemplate: '\n\n{{subst:FineCons|cancellata}} --~~~~',
consensualeDeletedSummary: 'notifica dell\'avvenuta cancellazione in modalità consensuale',
consensualeDeletedReason: 'Come da procedura di [[WP:RPC|cancellazione consensuale]]: [[$1]]',
consensualeKeptTemplate: '\n\n{{subst:FineCons|mantenuta}} --~~~~',
consensualeKeptSummary: 'notifica dell\'avvenuto mantenimento in modalità consensuale',
votazioneDeletedTemplate: '\n\n{{subst:FineVoto|cancellata}} --~~~~',
votazioneDeletedSummary: 'notifica dell\'avvenuta cancellazione in seguito a votazione',
votazioneDeletedReason: 'Come da [[WP:RPC|votazione sulla cancellazione]]: [[$1]]',
votazioneKeptTemplate: '\n\n{{subst:FineVoto|mantenuta}} --~~~~',
votazioneKeptSummary: 'notifica dell\'avvenuto mantenimento in seguito a votazione',
deletedTalkReason: '([[WP:IMMEDIATA|C10]]) Discussione di pagina cancellata: [[$1]]',
// [[Template:Cronologia valutazioni/man]]
assessmentsHistoryDefaultParams: {
azione: 'PDC',
data: '{{subst:LOCALDAY}} {{subst:LOCALMONTHNAME}} {{subst:LOCALYEAR}}'
},
assessmentsHistoryUpdateSummary: 'aggiornamento di Cronologia valutazioni',
// [[Template:Cancellazione/richiesta]] per vecchie procedure
nominationTemplateRegex: /\{\{\s*[Cc]ancellazione\/(?:proposta|richiesta)\s*\|\s*(?:1\s*\=\s*|)([^\{\|\}]+)\s*(\}\}|\|)/,
// [[Wikipedia:Regole per la cancellazione#Annullamento della cancellazione]]
cancelledReplace: /(\{\{\s*[Cc]ancellazione\/proposta\|.+?)(\}\})/,
cancelledReplaceWith: '$1|annullata$2',
cancelledTemplate: 'subst:Interrotto|Procedura annullata',
cancelledSummary: 'procedura annullata',
removeNominationNoticeReplace: /(<noinclude>)?\s*\{\{\s*[Cc]ancellazione.*?\}\}\s*(<\/noinclude>)?\n+/,
removeNominationNoticeReplaceWith: '',
removeNominationNoticeSummary: 'rimozione del template Cancellazione',
protectLevel: 'edit=sysop|move=sysop',
protectReason: '[[WP:PDC|Procedura di cancellazione]] terminata o annullata'
},
/**
* Messaggi di interfaccia per la lingua italiana.
*/
i18n: {
it: {
'menu-link-label': 'Richiedi cancellazione',
'menu-link-tooltip': 'Procedura guidata per richiedere la cancellazione di questa pagina',
'dialog-title': 'Richiesta di cancellazione: procedura guidata',
'dialog-button-cancel': 'Annulla',
'dialog-button-proceed': 'Procedi',
'dialog-button-final': 'Richiedi la cancellazione',
'error-msg': '$1: $2',
'process-init': '{{GENDER:$1|Benvenuto|Benvenuta|Benvenuto/a}}!<br>Sarai {{GENDER:$1|guidato|guidata|guidato/a}} nella richiesta di cancellazione per la pagina "<b>$2</b>".<br><br>Se invece desideri effettuare la procedura manualmente, consulta $3.',
'process-loading-contributors': 'Caricamento dei contributori della pagina in corso...',
'process-confirm': 'Stai per proporre la cancellazione della pagina "$1".',
'option-reason': 'Perché la pagina dovrebbe essere cancellata? (La firma è inserita automaticamente)',
'option-reason-missing': 'Inserisci una motivazione',
'option-notify-creator': 'Notifica il creatore della pagina ($1)',
'option-notify-biggest': 'Notifica l\'utente registrato con più contributi alla pagina ($1)',
'option-notify-topics': 'Eventuale/i argomento/i relativo/i: ',
'option-notify-wikiprojects': 'Invia notifiche ai progetti di riferimento',
'new-nomination-wait': 'Creazione della pagina di procedura in corso...',
'new-nomination-error': 'Errore durante la creazione della pagina di procedura',
'nominate-wait': 'Aggiunta dell\'avviso nella pagina in corso...',
'nominate-error': 'Errore durante l\'aggiunta dell\'avviso nella pagina',
'notify-wait': 'Notifica della proposta di cancellazione in corso...',
'notify-error': 'Errore durante la notifica della proposta di cancellazione',
'notify-done': 'Notifica della proposta di cancellazione inviata con successo alla pagina "$1"',
'toolbox-title': 'Strumenti PDC per "$1"',
'toolbox-days-ago': '$1 {{PLURAL:$1|giorno|giorni}} fa',
'toolbox-today': 'oggi',
'toolbox-yesterday': 'ieri',
'toolbox-user-unknown': 'un utente sconosciuto',
'toolbox-open-generic': 'Procedura aperta',
'toolbox-open': 'Procedura aperta $1 da $2',
'toolbox-closed': 'Procedura chiusa',
'toolbox-purge': 'Aggiorna',
'toolbox-defer': 'Proroga',
'toolbox-defer-deferrable': 'Proroga la procedura',
'toolbox-defer-already-poll': 'Già in votazione',
'toolbox-defer-already-deferred': 'Già prorogata',
'toolbox-defer-not-deferrable-yet': 'Non ancora prorogabile',
'toolbox-defer-days': 'Giorni di proroga',
'toolbox-defer-cancel': 'Non prorogare',
'toolbox-defer-wait': 'Proroga della procedura in corso...',
'toolbox-defer-error': 'Errore durante la proroga della procedura',
'toolbox-consensuale': 'Passa alla modalità consensuale',
'toolbox-consensuale-cancel': 'Annulla',
'toolbox-consensuale-reason': 'Perché non vuoi che la pagina sia cancellata?',
'toolbox-consensuale-wait': 'Passaggio alla modalità consensuale in corso...',
'toolbox-consensuale-error': 'Errore durante il passaggio alla modalità consensuale',
'toolbox-assessments-history-update-wait': 'Aggiornamento di Cronologia valutazioni in corso...',
'toolbox-assessments-history-update-error': 'Errore durante l\'aggiornamento di Cronologia valutazioni',
'toolbox-cancel': 'Annulla la procedura',
'toolbox-cancel-cancel': 'Non annullare la procedura',
'toolbox-cancel-reason': 'Perché la procedura deve essere annullata?',
'toolbox-cancel-wait': 'Annullamento della procedura in corso...',
'toolbox-cancel-error': 'Errore durante l\'annullamento della procedura',
'toolbox-cancel-protect-wait': 'Protezione della pagina di procedura in corso...',
'toolbox-cancel-protect-error': 'Errore durante la protezione della procedura',
'toolbox-vote': 'Votazione',
'toolbox-vote-for': 'Vota per $1',
'toolbox-vote-wait': 'Invio del voto in corso...',
'toolbox-vote-error': 'Errore durante l\'invio del voto',
'toolbox-sysops': 'Per gli amministratori',
'toolbox-vote-start': 'Avvia votazione',
'toolbox-vote-start-wait': 'Avvio della votazione in corso...',
'toolbox-vote-start-error': 'Errore durante l\'avvio della votazione',
'toolbox-close': 'Chiudi la procedura',
'toolbox-close-delete': 'Cancellare la pagina?',
'toolbox-close-delete-yes': 'Sì',
'toolbox-close-delete-no': 'No',
'toolbox-close-cancel': 'Annulla',
'toolbox-close-deletetalk': 'Cancellare la pagina di discussione?',
'toolbox-close-deletetalk-yes': 'Sì',
'toolbox-close-deletetalk-no': 'No',
'toolbox-close-option-protect': 'Proteggi questa procedura',
'toolbox-close-kept-wait': 'Notifica dell\'avvenuto mantenimento della pagina in corso...',
'toolbox-close-kept-error': 'Errore durante la notifica dell\'avvenuto mantenimento',
'toolbox-close-remove-notice-wait': 'Rimozione dell\'avviso di cancellazione dalla pagina in corso...',
'toolbox-close-remove-notice-error': 'Errore durante la rimozione dell\'avviso di cancellazione dalla pagina',
'toolbox-close-delete-wait': 'Cancellazione della pagina in corso...',
'toolbox-close-delete-error': 'Errore durante la cancellazione della pagina',
'toolbox-close-deletetalk-wait': 'Cancellazione della pagina di discussione in corso...',
'toolbox-close-deletetalk-error': 'Errore durante la cancellazione della pagina di discussione',
'toolbox-close-notice-wait': 'Notifica dell\'avvenuta cancellazione della pagina in corso...',
'toolbox-close-notice-error': 'Errore durante la notifica dell\'avvenuta cancellazione',
'toolbox-close-protect-wait': 'Protezione della pagina di procedura in corso...',
'toolbox-close-protect-error': 'Errore durante la protezione della procedura',
'toolbox-purge-wait': 'Purge della pagina di procedura in corso...'
}
},
msg: function () {
return this.agent.msg.apply( this.agent, arguments );
},
l10nMsg: function () {
return this.agent.l10nMsg.apply( this.agent, arguments );
},
sysop: ( mw.config.get( 'wgUserGroups' ).indexOf( 'sysop' ) !== -1 || mw.config.get( 'wgUserName' ) === 'Ricordisamoa' ),
/**
* Genera i pulsanti per votare in una procedura di cancellazione.
*/
defineVoteButtons: function () {
/**
* @class VoteButtons
* @extends OO.ui.PanelLayout
*
* @constructor
* @param {Object} config - Opzioni di configurazione
* @cfg {PdcAgent} agent
* @cfg {string} pageName
* @cfg {ProgressHandler} progressHandler
* @cfg {Function} getVoteOutcome
* @cfg {VoteCounter} voteCounter
*/
VoteButtons = function ( config ) {
VoteButtons.parent.call( this, { expanded: false } );
this.agent = config.agent;
this.pageName = config.pageName;
this.progressHandler = config.progressHandler;
this.getVoteOutcome = config.getVoteOutcome;
this.voteCounter = config.voteCounter;
this.addButtons();
};
OO.inheritClass( VoteButtons, OO.ui.PanelLayout );
/**
* Gestisce il clic su un collegamento per votare.
*
* @private
* @param {Object} cfg - L'oggetto corrispondente alla sezione in cui votare
* @param {jQuery.Event} event - L'evento del clic
*/
VoteButtons.prototype.onVoteLinkClick = function ( cfg, event ) {
var self = this;
event.preventDefault();
self.progressHandler.showMessage( self.agent.msg( 'toolbox-vote-wait' ) );
self.agent.vota( self.pageName, cfg.num, '' )
.done( function () {
window.location.reload();
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-vote-error', info ) );
} );
};
/**
* Restituisce un collegamento per votare in una determinata sezione della procedura.
*
* @private
* @param {string} sectionId - Il nome univoco della sezione in cui votare
* @param {Object} cfg - L'oggetto corrispondente alla sezione in cui votare
* @return {jQuery}
*/
VoteButtons.prototype.getVoteLink = function ( sectionId, cfg ) {
return $( '<a>' )
.text( this.agent.msg( 'toolbox-vote-for', sectionId ) )
.attr( {
href: '#'
} )
.click( this.onVoteLinkClick.bind( this, cfg ) );
};
/**
* Restituisce una voce dell'elenco delle sezioni di votazione.
*
* @private
* @param {string} outcome - Il nome univoco della sezione attualmente vincente
* @param {Object} cfg - L'oggetto corrispondente alla sezione a cui la voce si riferisce
* @param {string} sectionId - Il nome univoco della sezione a cui la voce si riferisce
* @return {jQuery}
*/
VoteButtons.prototype.mapSections = function ( outcome, cfg, sectionId ) {
return $( '<li>' )
.prepend(
$( '<img>' )
.attr( {
src: cfg.icon,
alt: sectionId
} )
)
.append( ' ' )
.append(
$( '<a>' )
.text( cfg.votes )
.attr( {
href: '#' + sectionId
} )
.css( outcome === sectionId ? { 'font-weight': 'bold' } : {} )
)
.append( ' — ' )
.append( this.getVoteLink( sectionId, cfg ) );
};
/**
* Aggiunge l'elenco delle sezioni di votazione con i collegamenti per votare.
*
* @private
*/
VoteButtons.prototype.addButtons = function () {
var sections, outcome,
voteCounts = {},
$ul = $( '<ul>' ).appendTo( this.$element );
sections = this.voteCounter.getSections();
$.each( sections, function ( sectionId, cfg ) {
voteCounts[ sectionId ] = cfg.votes;
} );
outcome = this.getVoteOutcome( voteCounts );
$ul.append( $.map( sections, this.mapSections.bind( this, outcome ) ) );
};
},
defineProgressHandler: function () {
/**
* @class ProgressHandler
* @mixins OO.EventEmitter
*
* @constructor
*/
ProgressHandler = function () {
OO.EventEmitter.call( this );
this.bar = new OO.ui.ProgressBarWidget();
this.actions = null;
this.done = 0;
this.$text = $( '<p>' );
this.$container = $( '<div>' ).append( [
this.$text.hide(),
this.bar.$element.hide()
] );
};
OO.mixinClass( ProgressHandler, OO.EventEmitter );
/**
* Un evento 'message' viene emesso quando viene impostato un messaggio di progresso.
*
* @event message
* @param {string} messaggio - Il messaggio di progresso impostato
*/
/**
* Un evento 'error' viene emesso quando viene impostato un messaggio di errore.
*
* @event error
* @param {string} messaggio - Il messaggio di errore impostato
*/
/**
* Imposta il numero totale delle azioni da compiere.
*
* @param {number} actions - Numero di azioni
*/
ProgressHandler.prototype.setActions = function ( actions ) {
this.actions = actions;
this.updateProgress();
};
/**
* Incrementa di un'unità il numero delle azioni completate.
*/
ProgressHandler.prototype.tick = function () {
this.done++;
this.updateProgress();
};
/**
* Aggiorna la barra di progresso in base alla percentuale di azioni completate.
*
* @private
*/
ProgressHandler.prototype.updateProgress = function () {
this.bar.setProgress( this.actions !== null ? this.done / this.actions * 100 : false );
};
/**
* Imposta il messaggio relativo all'azione attuale.
*
* @param {string} messaggio - Il messaggio da impostare
*/
ProgressHandler.prototype.showMessage = function ( messaggio ) {
console.info( messaggio );
this.$text.empty().removeClass( 'error' ).show().append( messaggio );
this.bar.$element.show();
this.emit( 'message', messaggio );
};
/**
* Imposta un messaggio di errore relativo all'azione attuale.
*
* @param {string} messaggio - Il messaggio da impostare
*/
ProgressHandler.prototype.showError = function ( messaggio ) {
console.error( messaggio );
this.$text.empty().addClass( 'error' ).show().append( messaggio );
this.bar.$element.hide();
this.emit( 'error', messaggio );
};
},
defineLookupWidget: function () {
/**
* @class AllCategoriesLookupWidget
* @extends OO.ui.TextInputWidget
* @mixins OO.ui.mixin.LookupElement
*
* @constructor
* @param {Object} config Configuration options
* @cfg {mw.Api} api MediaWiki API instance
* @cfg {string} categoryPrefix The titles of the suggested categories should start with it
*/
AllCategoriesLookupWidget = function ( config ) {
OO.ui.TextInputWidget.call( this, config );
OO.ui.mixin.LookupElement.call( this, config );
this.api = config.api;
this.categoryPrefix = config.categoryPrefix;
};
OO.inheritClass( AllCategoriesLookupWidget, OO.ui.TextInputWidget );
OO.mixinClass( AllCategoriesLookupWidget, OO.ui.mixin.LookupElement );
AllCategoriesLookupWidget.prototype.getLookupRequest = function () {
return this.api.get( {
action: 'query',
format: 'json',
formatversion: 2,
list: 'allcategories',
acprefix: this.categoryPrefix,
acprop: '',
acfrom: this.categoryPrefix + this.value,
aclimit: 10
} );
};
AllCategoriesLookupWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
var self = this;
if ( response.query === undefined || response.query.allcategories === undefined ) {
return [];
}
return $.map( response.query.allcategories || [], function ( e ) {
return e.category.replace( self.categoryPrefix, '' );
} );
};
AllCategoriesLookupWidget.prototype.getLookupMenuOptionsFromData = function ( data ) {
return $.map( data, function ( value ) {
return new OO.ui.MenuOptionWidget( {
data: value,
label: value
} );
} );
};
},
defineDialog: function () {
var dialogMsg, // FIXME: https://phabricator.wikimedia.org/T129972
deferMsg = function ( arg ) {
return function () {
return dialogMsg( arg );
};
};
/**
* @class PdcDialog
* @extends OO.ui.ProcessDialog
*
* @constructor
* @param {Object} config - Opzioni di configurazione
* @cfg {string} afdCatPrefix - Prefisso delle categorie di pagine in cancellazione
* @cfg {PdcAgent} agent
* @cfg {mw.Api} api
* @cfg {string} helpPageTitle - Il titolo della pagina sulle regole per la cancellazione
* @cfg {Object} namespaces - I namespace del sito
* @cfg {ProgressHandler} progressHandler - Gestore della barra di progresso
* @cfg {string} titolo - Il titolo della pagina attuale
* @cfg {number} wikiprojectNamespace - Il numero del namespace "Progetto"
*/
PdcDialog = function ( config ) {
PdcDialog.parent.call( this, config );
this.afdCatPrefix = config.afdCatPrefix;
this.agent = config.agent;
this.api = config.api;
this.helpPageTitle = config.helpPageTitle;
this.namespaces = config.namespaces;
this.progressHandler = config.progressHandler;
this.titolo = config.titolo;
// namespace "Discussioni progetto"
this.wikiprojectTalkNamespace = config.wikiprojectNamespace + 1;
dialogMsg = this.agent.msg.bind( this.agent );
};
OO.inheritClass( PdcDialog, OO.ui.ProcessDialog );
PdcDialog.static.name = 'PdcDialog';
PdcDialog.static.title = 'PDC.js';
PdcDialog.static.size = 'large';
PdcDialog.static.actions = [
{
action: 'proceed',
modes: 'step1',
label: deferMsg( 'dialog-button-proceed' ),
flags: [ 'primary', 'progressive' ]
},
{
action: 'final',
modes: 'step2',
label: deferMsg( 'dialog-button-final' ),
flags: [ 'primary', 'constructive' ]
},
{
action: 'cancel',
modes: [ 'step1', 'step2' ],
label: deferMsg( 'dialog-button-cancel' ),
flags: 'safe'
}
];
/**
* @inheritdoc
*/
PdcDialog.prototype.initialize = function () {
PdcDialog.parent.prototype.initialize.apply( this, arguments );
this.content = new OO.ui.PanelLayout( { padded: true } );
this.fieldset = new OO.ui.FieldsetLayout( {
label: this.agent.msg( 'dialog-title' ), icon: 'alert'
} );
this.description = new OO.ui.LabelWidget( {
padded: true,
label: $( '<p>' )
.append(
this.agent.msg(
'process-init',
'', // utente attuale per GENDER
this.titolo,
$( '<a>' ).attr( 'href', mw.util.getUrl( this.helpPageTitle ) ).text( this.helpPageTitle ).get( 0 ).outerHTML
)
)
} );
this.fieldset.addItems( [ this.description ] );
this.content.$element.append( [
this.fieldset.$element,
this.progressHandler.$container
] );
this.$body.append( this.content.$element );
this.actions.once( 'add', function () {
this.actions.setMode( 'step1' );
}.bind( this ) );
this.options = {};
};
/**
* Aggiunge la casella per specificare il motivo della richiesta di cancellazione.
*
* @private
*/
PdcDialog.prototype.addReasonWidget = function () {
this.options.reason = new OO.ui.TextInputWidget( {
multiline: true,
autosize: true,
validate: /\S/
} );
this.fieldset.addItems( [
new OO.ui.FieldLayout(
this.options.reason,
{
label: this.agent.msg( 'option-reason' ),
align: 'top'
}
)
] );
};
/**
* Aggiunge l'opzione per notificare la procedura al primo autore della pagina.
*
* @private
*/
PdcDialog.prototype.addNotifyCreatorOption = function () {
if (
this.creatore.anon === undefined &&
this.creatore.user !== mw.config.get( 'wgUserName' )
) {
this.options.notifyCreator = new OO.ui.CheckboxInputWidget( {} );
this.fieldset.addItems( [
new OO.ui.FieldLayout(
this.options.notifyCreator,
{
align: 'inline',
label: $( '<span>' )
.append( this.agent.msg(
'option-notify-creator',
this.agent.linkUtente( this.creatore.user )
) )
}
)
] );
}
};
/**
* Aggiunge l'opzione per notificare la procedura al maggior contributore della pagina.
*
* @private
*/
PdcDialog.prototype.addNotifyBiggestOption = function () {
if (
this.maggiore !== null &&
this.maggiore !== this.creatore.user &&
this.maggiore !== mw.config.get( 'wgUserName' )
) {
this.options.notifyBiggest = new OO.ui.CheckboxInputWidget( {} );
this.fieldset.addItems( [
new OO.ui.FieldLayout(
this.options.notifyBiggest,
{
align: 'inline',
label: $( '<span>' )
.append( this.agent.msg(
'option-notify-biggest',
this.agent.linkUtente( this.maggiore )
) )
}
)
] );
}
};
/**
* Aggiunge le caselle per specificare gli argomenti trattati dalla pagina da cancellare.
*
* @private
*/
PdcDialog.prototype.addNotifyTopicOptions = function () {
this.options.notifyTopic1 = new AllCategoriesLookupWidget( {
$overlay: this.$overlay,
api: this.api,
categoryPrefix: this.afdCatPrefix
} );
this.fieldset.addItems( [
new OO.ui.FieldLayout(
this.options.notifyTopic1,
{
align: 'left',
label: this.agent.msg( 'option-notify-topics' )
}
)
] );
this.options.notifyTopic2 = new AllCategoriesLookupWidget( {
$overlay: this.$overlay,
api: this.api,
categoryPrefix: this.afdCatPrefix
} );
this.fieldset.addItems( [
new OO.ui.FieldLayout(
this.options.notifyTopic2,
{
align: 'left',
label: '+'
}
)
] );
};
/**
* Aggiunge l'opzione per notificare la procedura ai progetti competenti.
*
* @private
*/
PdcDialog.prototype.addNotifyWikiprojectsOption = function () {
this.options.notifyWikiprojects = new OO.ui.CheckboxInputWidget( {
disabled: this.namespaces[ this.wikiprojectTalkNamespace ] === undefined
} );
this.fieldset.addItems( [
new OO.ui.FieldLayout(
this.options.notifyWikiprojects,
{
align: 'inline',
label: this.agent.msg( 'option-notify-wikiprojects' )
}
)
] );
};
/**
* Aggiorna la finestra con le opzioni per richiedere la cancellazione della pagina.
*
* @private
* @param {Object[]} contributori - Le revisioni della pagina
*/
PdcDialog.prototype.onGetContributors = function ( contributori ) {
this.popPending();
this.description.setLabel(
$( '<p>' )
.append(
this.agent.msg( 'process-confirm', this.titolo )
)
);
this.creatore = contributori[ contributori.length - 1 ];
this.maggiore = this.agent.maggiorContributore( contributori );
this.addReasonWidget();
this.addNotifyCreatorOption();
this.addNotifyBiggestOption();
this.addNotifyTopicOptions();
this.addNotifyWikiprojectsOption();
// Forza il ridimensionamento della finestra
this.updateSize();
// Mostra il pulsante 'richiedi la cancellazione' al posto di 'procedi'
this.actions.setMode( 'step2' );
};
/**
* Richiede i contributori della pagina e aggiorna la finestra.
*
* @private
*/
PdcDialog.prototype.proceed = function () {
this.pushPending();
this.agent.ottieniContributori( this.titolo )
.done( this.onGetContributors.bind( this ) );
};
/**
* Ottiene i titoli delle pagine in cui notificare la procedura di cancellazione.
*
* @private
* @param {string[]} argomenti
* @return {string[]}
*/
PdcDialog.prototype.getNotificationPages = function ( argomenti ) {
var daNotificare,
self = this;
daNotificare = $.map( {
notifyCreator: self.creatore.user,
notifyBiggest: self.maggiore
}, function ( user, opt ) {
if (
self.options[ opt ] !== undefined &&
self.options[ opt ].isSelected()
) {
return self.namespaces[ 3 ] + ':' + user;
}
} );
if (
!self.options.notifyWikiprojects.isDisabled() &&
self.options.notifyWikiprojects.isSelected()
) {
daNotificare = daNotificare.concat(
$.map( argomenti, function ( argomento ) {
return self.namespaces[ self.wikiprojectTalkNamespace ] + ':' + argomento;
} )
);
}
return daNotificare;
};
/**
* Nomina la pagina per la cancellazione e segnala la procedura dove necessario.
*
* @private
*/
PdcDialog.prototype.final = function () {
var self = this,
motivazione = self.options.reason.getValue().trim(),
argomenti = $.map( [ 'notifyTopic1', 'notifyTopic2' ], function ( opt ) {
return self.options[ opt ].getValue().trim();
} )
.filter( function ( el, i, arr ) {
// Elimina i duplicati
return el !== '' && arr.indexOf( el ) === i;
} ),
daNotificare = self.getNotificationPages( argomenti );
self.progressHandler.setActions( 3 );
self.progressHandler.showMessage( self.agent.msg( 'new-nomination-wait' ) );
self.agent.creaProceduraDaPagina( self.titolo, motivazione )
.done( function ( procedura, numero ) {
self.progressHandler.tick();
self.progressHandler.showMessage( self.agent.msg( 'nominate-wait' ) );
self.agent.aggiungiAvvisoVoce( self.titolo, numero, argomenti )
.done( function () {
self.progressHandler.tick();
self.progressHandler.showMessage( self.agent.msg( 'notify-wait' ) );
self.agent.notificaProcedura( self.titolo, numero, daNotificare )
.done( function () {
self.progressHandler.tick();
window.location = mw.util.getUrl( procedura );
} )
.fail( function () {
self.progressHandler.showError( self.agent.msg( 'notify-error' ) );
} );
} )
.fail( function () {
self.progressHandler.showError( self.agent.msg( 'nominate-error' ) );
} );
} )
.fail( function () {
self.progressHandler.showError( self.agent.msg( 'new-nomination-error' ) );
} );
};
/**
* Controlla la validità della motivazione e procede in caso di esito positivo.
*
* @private
*/
PdcDialog.prototype.checkReasonAndFinal = function () {
this.options.reason.getValidity()
.done( this.final.bind( this ) );
};
/**
* @inheritdoc
*/
PdcDialog.prototype.getActionProcess = function ( action ) {
if ( action === 'proceed' ) {
return new OO.ui.Process( this.proceed, this );
}
if ( action === 'final' ) {
return new OO.ui.Process( this.checkReasonAndFinal, this );
}
if ( action === 'cancel' ) {
return new OO.ui.Process( this.close() );
}
return PdcDialog.parent.prototype.getActionProcess.call( this, action );
};
},
/**
* Avvia una finestra di dialogo per guidare l'utente durante l'avvio della procedura.
*
* @param {string} titolo - Il titolo della pagina della quale proporre la cancellazione
*/
proceduraGuidata: function ( titolo ) {
var self = this;
titolo = titolo.replace( /_/g, ' ' );
mw.loader.using( self.dependencies.dialog )
.done( function () {
var windowManager;
if ( AllCategoriesLookupWidget === undefined ) {
self.defineLookupWidget();
}
self.defineDialog();
windowManager = new OO.ui.WindowManager();
$( 'body' ).append( windowManager.$element );
if ( ProgressHandler === undefined ) {
self.defineProgressHandler();
}
self.progressHandler = new ProgressHandler();
self.dialog = new PdcDialog( {
afdCatPrefix: self.config.afdCatPrefix,
agent: self.agent,
api: self.api,
helpPageTitle: self.config.help,
namespaces: self.namespaces,
progressHandler: self.progressHandler,
titolo: titolo,
wikiprojectNamespace: self.config.wikiprojectNamespace
} );
windowManager.addWindows( [ self.dialog ] );
windowManager.openWindow( self.dialog );
} );
},
/**
* Trasforma alcune frasi appositamente configurate
* in link per richiedere la cancellazione della pagina.
*/
autoRfd: function () {
var self = this;
if ( self.config.autoRfd.length === 0 ) {
return;
}
$( 'div' ).each( function () {
$( this )
.contents()
.filter( function () {
// solo testo semplice
return this.nodeType === this.TEXT_NODE;
} )
.each( function () {
var htmlDiv = this;
$.each( self.config.autoRfd, function ( replIdx, replParts ) {
// cerca la frase intera,
var node,
find = htmlDiv.textContent.indexOf( replParts.join( '' ) );
if ( find !== -1 ) {
// ...la isola
node = htmlDiv.splitText( find + replParts[ 0 ].length );
// ...e la rende cliccabile
$( node.splitText( replParts[ 1 ].length ).previousSibling )
.wrap( '<a>' ).parent()
.attr( {
href: '#',
title: self.msg( 'menu-link-tooltip' )
} )
.click( function ( event ) {
event.preventDefault();
self.proceduraGuidata( mw.config.get( 'wgPageName' ) );
} );
}
} );
} );
} );
},
/**
* Genera il contenitore per pulsanti che non richiedono permessi particolari.
*/
definePublicButtons: function () {
/**
* @class PublicButtons
* @extends OO.ui.PanelLayout
*
* @constructor
* @param {Object} config - Opzioni di configurazione
* @cfg {PdcAgent} agent
* @cfg {ProgressHandler} progressHandler
* @cfg {boolean} prorogabile - Se la procedura di cancellazione può essere prorogata
* @cfg {boolean} protectOnCancel - Se la procedura di cancellazione va protetta dopo l'annullamento
* @cfg {Object} stato - Lo stato della procedura di cancellazione
*/
PublicButtons = function ( config ) {
PublicButtons.parent.call( this, { expanded: false } );
this.agent = config.agent;
this.progressHandler = config.progressHandler;
this.prorogabile = config.prorogabile;
this.protectOnCancel = config.protectOnCancel;
this.stato = config.stato;
this.addButtons();
};
OO.inheritClass( PublicButtons, OO.ui.PanelLayout );
PublicButtons.prototype.switchButtons = function ( show ) {
var m = show ? 'show' : 'hide';
if ( show ) {
this.$element.next().remove();
}
return this.$element[ m ]();
};
/**
* Gestisce il clic sul pulsante "aggiorna".
*
* @private
*/
PublicButtons.prototype.onPurgeButtonClick = function () {
this.progressHandler.showMessage( this.agent.msg( 'toolbox-purge-wait' ) );
this.agent.purgaPagina( this.stato.procedura )
.done( function () {
window.location.reload();
} );
};
/**
* Genera il pulsante "aggiorna" con effetto immediato (innocuo).
*
* @private
* @return {OO.ui.ButtonWidget}
*/
PublicButtons.prototype.getPurgeButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-purge' )
} )
.on( 'click', this.onPurgeButtonClick.bind( this ) );
};
/**
* Gestisce il clic sul pulsante "proroga".
*
* @private
*/
PublicButtons.prototype.onDeferButtonClick = function () {
var self = this,
deferForm = new OO.ui.PanelLayout( { expanded: false } ),
$deferForm = deferForm.$element,
deferDays = new OO.ui.NumberInputWidget( {
min: self.agent.config.deferMinDays,
max: self.agent.config.deferMaxDays,
isInteger: true,
input: {
value: self.agent.config.deferDefaultDays
}
} ),
// Conferma
confirmButton = new OO.ui.ButtonWidget( {
label: self.agent.msg( 'toolbox-defer' ),
flags: [ 'constructive' ]
} )
.on( 'click', function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-defer-wait' ) );
self.agent.prorogaProcedura( self.stato.procedura, parseInt( deferDays.getValue() ) )
.done( function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-purge-wait' ) );
self.agent.purgaPagina( self.stato.procedura )
.done( function () {
window.location.reload();
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-defer-error', info ) );
} );
} ),
// Annulla
cancelButton = new OO.ui.ButtonWidget( {
label: self.agent.msg( 'toolbox-defer-cancel' )
} )
.on( 'click', function () {
self.switchButtons( true );
} );
$deferForm.append(
// Di quanti giorni?
new OO.ui.FieldLayout(
deferDays,
{
label: self.agent.msg( 'toolbox-defer-days' )
}
)
.$element,
confirmButton.$element,
cancelButton.$element
)
.insertAfter( self.switchButtons() );
};
/**
* Genera il pulsante "proroga" con conferma richiesta.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
PublicButtons.prototype.getDeferButton = function () {
var deferButtonTooltip;
if ( this.prorogabile ) {
deferButtonTooltip = 'toolbox-defer-deferrable';
} else if ( this.stato.votazione ) {
deferButtonTooltip = 'toolbox-defer-already-poll';
} else if ( this.stato.prorogata ) {
deferButtonTooltip = 'toolbox-defer-already-deferred';
} else {
deferButtonTooltip = 'toolbox-defer-not-deferrable-yet';
}
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-defer' ),
title: this.agent.msg( deferButtonTooltip ),
flags: [ 'progressive' ],
disabled: !this.prorogabile
} )
.on( 'click', this.onDeferButtonClick.bind( this ) );
};
/**
* Gestisce il clic sul pulsante "passa alla modalità consensuale".
*
* @private
*/
PublicButtons.prototype.onConsensualeButtonClick = function () {
var self = this,
consensualeForm = new OO.ui.PanelLayout( { expanded: false } ),
$consensualeForm = consensualeForm.$element,
// Motivazione
consensualeReason = new OO.ui.TextInputWidget( {
multiline: true,
autosize: true
} ),
// Conferma
confirmButton = new OO.ui.ButtonWidget( {
label: self.agent.msg( 'toolbox-consensuale' ),
flags: [ 'constructive' ]
} )
.on( 'click', function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-consensuale-wait' ) );
self.agent.consensuale( self.stato.procedura, consensualeReason.getValue() )
.done( function () {
window.location.reload();
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-consensuale-error', info ) );
} );
} ),
// Annulla
cancelButton = new OO.ui.ButtonWidget( {
label: self.agent.msg( 'toolbox-consensuale-cancel' )
} )
.on( 'click', function () {
self.switchButtons( true );
} );
$consensualeForm.append(
new OO.ui.FieldLayout(
consensualeReason,
{
label: self.agent.msg( 'toolbox-consensuale-reason' ),
align: 'top'
}
)
.$element,
confirmButton.$element,
cancelButton.$element
)
.insertAfter( self.switchButtons() );
};
/**
* Genera il pulsante "passa alla modalità consensuale" con conferma richiesta.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
PublicButtons.prototype.getConsensualeButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-consensuale' ),
flags: [ 'progressive' ]
} )
.on( 'click', this.onConsensualeButtonClick.bind( this ) );
};
/**
* Protegge la procedura di cancellazione dopo l'annullamento se richiesto.
*
* @private
*/
PublicButtons.prototype.maybeProtectOnCancel = function () {
if ( this.protectOnCancel ) {
this.progressHandler.showMessage( this.agent.msg( 'toolbox-cancel-protect-wait' ) );
return this.agent.proteggiPagina( this.stato.procedura );
}
return $.Deferred().resolve();
};
/**
* Gestisce il clic sul pulsante "annulla la procedura".
*
* @private
*/
PublicButtons.prototype.onCancelButtonClick = function () {
var self = this,
cancelForm = new OO.ui.PanelLayout( { expanded: false } ),
$cancelForm = cancelForm.$element,
// Motivazione
cancelReason = new OO.ui.TextInputWidget( {
multiline: true,
autosize: true
} ),
// Conferma
confirmButton = new OO.ui.ButtonWidget( {
label: self.agent.msg( 'toolbox-cancel' ),
flags: [ 'destructive' ]
} )
.on( 'click', function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-cancel-wait' ) );
self.agent.annullaProcedura( self.stato.procedura, cancelReason.getValue() )
.done( function () {
var parametri = {
esito: 'annullata',
collegamento: self.stato.procedura
};
self.progressHandler.showMessage( self.agent.msg( 'toolbox-assessments-history-update-wait' ) );
self.agent.aggiornaCronologiaValutazioni( self.stato.pagina, parametri )
.done( function () {
self.progressHandler.showMessage( '' );
self.maybeProtectOnCancel()
.done( function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-purge-wait' ) );
self.agent.purgaPagina( self.stato.procedura )
.done( function () {
window.location.reload();
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-cancel-protect-error', info ) );
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-assessments-history-update-error', info ) );
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-cancel-error', info ) );
} );
} ),
// Annulla
cancelButton = new OO.ui.ButtonWidget( {
label: self.agent.msg( 'toolbox-cancel-cancel' )
} )
.on( 'click', function () {
self.switchButtons( true );
} );
$cancelForm.append(
new OO.ui.FieldLayout(
cancelReason,
{
label: self.agent.msg( 'toolbox-cancel-reason' ),
align: 'top'
}
)
.$element,
confirmButton.$element,
cancelButton.$element
)
.insertAfter( self.switchButtons() );
};
/**
* Genera il pulsante "annulla la procedura" con conferma richiesta.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
PublicButtons.prototype.getCancelButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-cancel' ),
flags: [ 'progressive' ]
} )
.on( 'click', this.onCancelButtonClick.bind( this ) );
};
/**
* Aggiunge i pulsanti appropriati in base allo stato della procedura.
*/
PublicButtons.prototype.addButtons = function () {
this.$element.append( this.getPurgeButton().$element );
if ( !this.stato.terminata ) {
if ( this.stato.consensuale ) {
this.$element.append( this.getDeferButton().$element );
} else {
this.$element.append( this.getConsensualeButton().$element );
}
this.$element.append( this.getCancelButton().$element );
}
};
},
/**
* Genera il contenitore per pulsanti che richiedono permessi di amministratore.
*/
defineSysopButtons: function () {
/**
* @class SysopButtons
* @extends OO.ui.PanelLayout
*
* @constructor
* @param {Object} config - Opzioni di configurazione
* @cfg {PdcAgent} agent
* @cfg {ProgressHandler} progressHandler
* @cfg {Object} stato - Lo stato della procedura di cancellazione
* @cfg {VoteCounter} voteCounter
*/
SysopButtons = function ( config ) {
SysopButtons.parent.call( this, { expanded: false } );
this.agent = config.agent;
this.progressHandler = config.progressHandler;
this.stato = config.stato;
this.voteCounter = config.voteCounter;
this.$element.append( [
this.getVoteStartButton().$element,
this.getCloseButton().$element
] );
};
OO.inheritClass( SysopButtons, OO.ui.PanelLayout );
SysopButtons.prototype.switchButtons = function ( show ) {
var m = show ? 'show' : 'hide';
if ( show ) {
this.$element.next().remove();
}
return this.$element[ m ]();
};
/**
* Ottiene la modalità della procedura di cancellazione.
*
* @private
* @return {string}
*/
SysopButtons.prototype.getModeId = function () {
if ( this.stato.votazione ) {
return 'votazione';
}
if ( this.stato.consensuale ) {
return 'consensuale';
}
return 'simple';
};
/**
* Gestisce il clic sul pulsante "avvia votazione".
*
* @private
*/
SysopButtons.prototype.onVoteStartButtonClick = function () {
var self = this;
self.progressHandler.showMessage( self.agent.msg( 'toolbox-vote-start-wait' ) );
self.agent.avviaVotazione( self.stato.procedura )
.done( function () {
window.location.reload();
} )
.fail( function () {
self.progressHandler.showError( self.agent.msg( 'toolbox-vote-start-error' ) );
} );
};
/**
* Genera il pulsante "avvia votazione" con effetto immediato.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
SysopButtons.prototype.getVoteStartButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-vote-start' ),
flags: [ 'constructive' ],
disabled: ( this.stato.votazione || !this.stato.consensuale )
} )
.on( 'click', this.onVoteStartButtonClick.bind( this ) );
};
/**
* Genera il pulsante per rispondere "sì" alla cancellazione della pagina di discussione.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
SysopButtons.prototype.getCloseDeleteTalkYesButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-close-deletetalk-yes' ),
flags: [ 'destructive' ]
} );
};
/**
* Genera il pulsante per rispondere "no" alla cancellazione della pagina di discussione.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
SysopButtons.prototype.getCloseDeleteTalkNoButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-close-deletetalk-no' ),
flags: [ 'constructive' ]
} );
};
/**
* Chiede all'utente se cancellare la pagina di discussione.
*
* @private
* @return {jQuery.Promise}
*/
SysopButtons.prototype.askDeleteTalk = function ( titolo ) {
var self = this,
deferred = $.Deferred();
$( '<div>' )
.append( [
// Cancellare la pagina?
self.agent.msg( 'toolbox-close-deletetalk' ),
'<br>',
// Sì
self.getCloseDeleteTalkYesButton().$element.on( 'click', function () {
var motivazione = self.agent.l10nMsg( 'deletedTalkReason', self.stato.procedura );
self.switchButtons( true );
self.progressHandler.showMessage( self.agent.msg( 'toolbox-close-deletetalk-wait' ) );
self.agent.cancellaPagina( titolo, motivazione ).then( deferred.resolve, deferred.reject );
} ),
// No
self.getCloseDeleteTalkNoButton().$element.on( 'click', function () {
self.switchButtons( true );
deferred.resolve();
} )
] )
.insertAfter( self.switchButtons() );
return deferred;
};
/**
* Controlla l'esistenza dell'eventuale pagina di discussione e, in caso positivo, chiede all'utente se cancellarla.
*
* @private
* @return {jQuery.Promise}
*/
SysopButtons.prototype.maybeDeleteTalkPage = function () {
var self = this,
titolo = self.agent.ottieniTitoloDiscussione( self.stato.pagina );
if ( titolo === null ) {
return $.Deferred().resolve();
}
return self.agent.controllaEsistenzaPagina( titolo )
.then( function ( exists ) {
if ( exists ) {
return self.askDeleteTalk( titolo );
}
return $.Deferred().resolve();
} );
};
/**
* Gestisce il clic sul pulsante per rispondere "sì" alla cancellazione della pagina.
*
* @private
*/
SysopButtons.prototype.onCloseDeleteYesButtonClick = function () {
var self = this,
modalità = self.getModeId(),
// simpleDeletedReason, consensualeDeletedReason, votazioneDeletedReason
motivazione = self.agent.l10nMsg( modalità + 'DeletedReason', self.stato.procedura );
self.progressHandler.setActions( 5 );
self.progressHandler.showMessage( self.agent.msg( 'toolbox-close-delete-wait' ) );
self.agent.cancellaPagina( self.stato.pagina, motivazione )
.done( function () {
self.progressHandler.tick();
self.progressHandler.showMessage( '' );
self.maybeDeleteTalkPage()
.done( function () {
self.progressHandler.tick();
self.progressHandler.showMessage( self.agent.msg( 'toolbox-close-notice-wait' ) );
self.agent.terminaProcedura( self.stato.procedura, 'Deleted', modalità )
.done( function () {
self.progressHandler.tick();
self.progressHandler.showMessage( self.agent.msg( 'toolbox-close-protect-wait' ) );
self.agent.proteggiPagina( self.stato.procedura )
.done( function () {
self.progressHandler.tick();
self.progressHandler.showMessage( self.agent.msg( 'toolbox-purge-wait' ) );
self.agent.purgaPagina( self.stato.procedura )
.done( function () {
self.progressHandler.tick();
window.location.reload();
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-close-protect-error', info ) );
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-close-notice-error', info ) );
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-close-deletetalk-error', info ) );
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-close-delete-error', info ) );
} );
};
/**
* Genera il pulsante per rispondere "sì" alla cancellazione della pagina.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
SysopButtons.prototype.getCloseDeleteYesButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-close-delete-yes' ),
flags: [ 'destructive' ]
} )
.on( 'click', this.onCloseDeleteYesButtonClick.bind( this ) );
};
/**
* Aggiorna il template Cronologia valutazioni in seguito al mantenimento della pagina.
*
* @private
* @return {jQuery.Promise}
*/
SysopButtons.prototype.updateAssessmentsHistoryKept = function () {
var parametri, sections;
parametri = {
collegamento: this.stato.procedura
};
if ( this.stato.votazione ) {
sections = this.voteCounter.getSections();
if ( sections.Cancellare === undefined || sections.Mantenere === undefined ) {
return $.Deferred.reject();
}
parametri.si = sections.Cancellare.votes;
parametri.no = sections.Mantenere.votes;
}
return this.agent.aggiornaCronologiaValutazioni( this.stato.pagina, parametri );
};
/**
* Gestisce il clic sul pulsante per rispondere "no" alla cancellazione della pagina.
*
* @private
*/
SysopButtons.prototype.onCloseDeleteNoButtonClick = function () {
var self = this;
self.progressHandler.showMessage( self.agent.msg( 'toolbox-close-kept-wait' ) );
self.agent.terminaProcedura( self.stato.procedura, 'Kept', self.getModeId() )
.done( function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-assessments-history-update-wait' ) );
self.updateAssessmentsHistoryKept()
.done( function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-close-protect-wait' ) );
self.agent.proteggiPagina( self.stato.procedura )
.done( function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-close-remove-notice-wait' ) );
self.agent.rimuoviAvvisoVoce( self.stato.pagina )
.done( function () {
self.progressHandler.showMessage( self.agent.msg( 'toolbox-purge-wait' ) );
self.agent.purgaPagina( self.stato.procedura )
.done( function () {
window.location.reload();
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-close-remove-notice-error', info ) );
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-close-protect-error', info ) );
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-assessments-history-update-error', info ) );
} );
} )
.fail( function ( code, info ) {
self.progressHandler.showError( self.agent.errorMsg( 'toolbox-close-kept-error', info ) );
} );
};
/**
* Genera il pulsante per rispondere "no" alla cancellazione della pagina.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
SysopButtons.prototype.getCloseDeleteNoButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-close-delete-no' ),
flags: [ 'constructive' ]
} )
.on( 'click', this.onCloseDeleteNoButtonClick.bind( this ) );
};
/**
* Genera il pulsante per rispondere "annulla" alla cancellazione della pagina.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
SysopButtons.prototype.getCloseCancelButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-close-cancel' )
} )
.on( 'click', this.switchButtons.bind( this, true ) );
};
/**
* Gestisce il clic sul pulsante "chiudi la procedura".
*
* @private
*/
SysopButtons.prototype.onCloseButtonClick = function () {
$( '<div>' )
.append( [
// Cancellare la pagina?
this.agent.msg( 'toolbox-close-delete' ),
'<br>',
// Sì
this.getCloseDeleteYesButton().$element,
// No
this.getCloseDeleteNoButton().$element,
// Annulla
this.getCloseCancelButton().$element
] )
.insertAfter( this.switchButtons() );
};
/**
* Genera il pulsante "chiudi la procedura" con conferma richiesta.
*
* @private
* @return {OO.ui.ButtonWidget}
*/
SysopButtons.prototype.getCloseButton = function () {
return new OO.ui.ButtonWidget( {
label: this.agent.msg( 'toolbox-close' ),
flags: [ 'progressive' ]
} )
.on( 'click', this.onCloseButtonClick.bind( this ) );
};
},
/**
* Aggiunge un link nella barra laterale per avviare una procedura guidata.
*/
addPortletLink: function () {
var self = this;
$( mw.util.addPortletLink( 'p-tb', '#', self.msg( 'menu-link-label' ), 'PDC-init', self.msg( 'menu-link-tooltip' ) ) )
.click( function ( event ) {
event.preventDefault();
self.proceduraGuidata( mw.config.get( 'wgPageName' ) );
} );
},
/**
* Se opportuno, aggiunge un link nella barra laterale ed esegue autoRfd.
*/
portletMode: function () {
var self = this;
self.agent.inCancellazione( mw.config.get( 'wgPageName' ) )
.done( function ( val ) {
if ( val === false ) {
self.agent.verificaRequisiti()
.done( function ( accettato ) {
if ( accettato !== true ) {
return;
}
self.addPortletLink();
self.autoRfd();
} );
}
} );
},
/**
* Restituisce il contatore di voti, creandolo se necessario.
*
* @private
* @return {VoteCounter}
*/
getVoteCounter: function () {
if ( this.voteCounter === undefined ) {
this.voteCounter = new VoteCounter( {
$content: mw.util.$content,
pageName: mw.config.get( 'wgPageName' ),
voteNullItems: this.config.voteNullItems,
voteSections: this.config.voteSections
} );
}
return this.voteCounter;
},
/**
* Genera il box "Strumenti PDC" a partire dallo stato della procedura di cancellazione.
*
* @private
* @param {Object} stato - Lo stato della procedura di cancellazione
* @return {jQuery}
*/
getToolboxFromStatus: function ( stato ) {
var creazione, apertaDaGiorni, $toolbox, statusMsg, days, user,
prorogabile = false,
adesso = new Date();
if ( stato && stato.creazione && stato.creazione.timestamp ) {
creazione = new Date( stato.creazione.timestamp );
apertaDaGiorni = ( adesso - creazione ) / 86400000;
if (
stato.terminata === false &&
!stato.votazione &&
!stato.prorogata &&
apertaDaGiorni >= this.config.minDeferrableDays
) {
prorogabile = true;
}
}
$toolbox = $( '<div>' )
.addClass( 'toccolours' )
.css( 'font-size', '100%' )
.append(
$( '<h3>' )
.text( this.msg( 'toolbox-title', stato.pagina ) )
);
statusMsg = this.msg( 'toolbox-open-generic' );
if ( ProgressHandler === undefined ) {
this.defineProgressHandler();
}
this.progressHandler = new ProgressHandler();
this.progressHandler.on( 'message', function () {
$toolbox.find( '.oo-ui-buttonElement' ).hide();
} );
$toolbox.prepend( this.progressHandler.$container );
if ( stato.terminata ) {
statusMsg = this.msg( 'toolbox-closed' );
} else if ( apertaDaGiorni ) {
if ( parseInt( apertaDaGiorni ) > 1 ) {
days = this.msg( 'toolbox-days-ago', parseInt( apertaDaGiorni ) );
} else if ( adesso.getDate() === creazione.getDate() ) {
days = this.msg( 'toolbox-today' );
} else {
days = this.msg( 'toolbox-yesterday' );
}
if ( stato.creazione && stato.creazione.user ) {
user = this.agent.linkUtente( stato.creazione.user );
} else {
user = this.msg( 'toolbox-user-unknown' );
}
statusMsg = this.msg( 'toolbox-open', days, user );
}
$( '<p>' )
.append( statusMsg )
.appendTo( $toolbox );
if ( PublicButtons === undefined ) {
this.definePublicButtons();
}
$toolbox
.append( new PublicButtons( {
agent: this.agent,
progressHandler: this.progressHandler,
prorogabile: prorogabile,
protectOnCancel: this.sysop,
stato: stato
} ).$element );
if ( stato.votazione && stato.terminata === false ) {
// Strumenti per votare
if ( VoteButtons === undefined ) {
this.defineVoteButtons();
}
$toolbox
.append( [
$( '<h4>' )
.text( this.msg( 'toolbox-vote' ) ),
new VoteButtons( {
agent: this.agent,
pageName: mw.config.get( 'wgPageName' ),
progressHandler: this.progressHandler,
getVoteOutcome: this.config.getVoteOutcome,
voteCounter: this.getVoteCounter()
} ).$element
] );
}
if ( this.sysop && stato.terminata === false ) {
// Strumenti per amministratori
if ( SysopButtons === undefined ) {
this.defineSysopButtons();
}
$toolbox
.append( [
$( '<h4>' )
.text( this.msg( 'toolbox-sysops' ) ),
new SysopButtons( {
agent: this.agent,
progressHandler: this.progressHandler,
stato: stato,
voteCounter: this.getVoteCounter()
} ).$element
] );
}
return $toolbox;
},
/**
* Se opportuno, aggiunge il box "Strumenti PDC".
*/
toolboxMode: function () {
var self = this;
self.agent.verificaRequisiti()
.done( function ( accettato ) {
if ( accettato !== true ) {
return;
}
self.agent.ottieniTitoloPagina( mw.config.get( 'wgPageName' ) )
.done( function ( titoloPagina ) {
self.agent.ottieniStatoProcedura( mw.config.get( 'wgPageName' ) )
.done( function ( stato ) {
stato.pagina = titoloPagina;
self.getToolboxFromStatus( stato ).prependTo( '#mw-content-text' );
} );
} );
} );
},
/**
* Se lo script è utile nella pagina, carica le dipendenze e lo avvia.
*/
preInit: function () {
var self = this;
if (
// pagina esistente
mw.config.get( 'wgArticleId' ) > 0 &&
// in modalità di visualizzazione
mw.config.get( 'wgAction' ) === 'view' &&
// niente redirect
mw.config.get( 'wgIsRedirect' ) === false &&
// niente diff
mw.util.getParamValue( 'diff' ) === null &&
// solo ultime versioni
mw.util.getParamValue( 'oldid' ) === null
) {
mw.loader.using( 'mediawiki.user' )
.done( function () {
var sp, modes, values;
// solo utenti registrati
if ( mw.user.isAnon() !== false ) {
return;
}
sp = mw.config.get( 'wgPageName' ).replace( /_/g, ' ' ).split( '/' );
modes = {
// visualizzare la casella "Strumenti PDC"?
toolbox: ( sp.length > 1 && sp[ 0 ] === self.config.base ),
// aggiungere il link per la finestra di dialogo alla sezione "Strumenti" della barra laterale?
portlet: (
mw.config.get( 'wgIsArticle' ) === true &&
self.config.actInNamespaces.indexOf( mw.config.get( 'wgNamespaceNumber' ) ) !== -1
)
};
values = $.map( modes, function ( val ) {
return val;
} );
if ( values.indexOf( true ) !== -1 ) {
mw.loader.using( self.dependencies.general )
.done( function () {
self.init( modes );
} );
}
} );
}
},
/**
* Prepara i messaggi nella lingua dell'utente e nelle lingue alternative.
*
* @private
* @return {mw.Map}
*/
getMessagesWithFallback: function () {
var i, langCode,
chain = mw.language.getFallbackLanguageChain(),
messages = new mw.Map();
for ( i = chain.length - 1; i >= 0; i-- ) {
langCode = chain[ i ];
if ( this.i18n.hasOwnProperty( langCode ) ) {
messages.set( this.i18n[ langCode ] );
}
}
return messages;
},
/**
* Avvia lo script senza caricare le dipendenze.
*
* @private
* @param {Object} modes - Le modalità da attivare
*/
init: function ( modes ) {
this.i18n = this.getMessagesWithFallback();
this.agent = new PdcAgent( {
api: this.api,
assessmentsHistoryEditor: new AssessmentsHistoryEditor(),
i18n: this.i18n,
l10n: this.config,
namespaces: this.namespaces
} );
if ( modes.portlet === true ) {
this.portletMode();
}
if ( modes.toolbox === true ) {
this.toolboxMode();
}
}
};
PDC.preInit();
window.PDC = PDC;
}( mediaWiki, jQuery ) );
// </nowiki>