m (Erreurs) |
m (Erreur de mot clé) |
||
Ligne 107 : | Ligne 107 : | ||
if ( !row.source || !row.target ) { |
if ( !row.source || !row.target ) { |
||
$statusTd.css( 'color', 'darkred' ).html( '☒' ); |
$statusTd.css( 'color', 'darkred' ).html( '☒' ); |
||
− | + | break; |
|
} |
} |
||
Ligne 114 : | Ligne 114 : | ||
$tr.addClass( 'translation-list-uptodate' ); |
$tr.addClass( 'translation-list-uptodate' ); |
||
$statusTd.css( 'color', 'green' ).html( '☑' ); |
$statusTd.css( 'color', 'green' ).html( '☑' ); |
||
− | + | break; |
|
} |
} |
||
Version du 5 octobre 2020 à 15:32
$.when(
mw.loader.using( [ 'mediawiki.api', 'mediawiki.ForeignApi' ] ),
$.ready
).then( function () {
var sourceWikiRoot = 'https://bindingofisaacrebirth.gamepedia.com',
targetWikiRoot = 'https://bindingofisaacrebirth-fr.gamepedia.com',
sourceApi = new mw.ForeignApi( sourceWikiRoot + '/api.php' ),
targetApi = new mw.Api();
/**
* @typedef {{ pageid: string, title: string }} PageQueryResult
* @typedef {{ page: string, revision: string }} CargoQueryResult
* @typedef {{ source: PageQueryResult?, target: PageQueryResult?, oldRevision: number, newRevision: number }} RowData
*/
$( '.translation-list' ).each( function () {
new TranslationList( $( this ) );
} );
/**
* @constructor
* @param {JQuery} $table
*/
function TranslationList( $table ) {
var self = this,
namespace = $table.attr( 'data-translation-list-ns' );
this.$table = $table;
this.namespace = namespace ? +namespace : 0;
/** @type {PageQueryResult[]} */
this.sourcePages = [];
/** @type {PageQueryResult[]} */
this.targetPages = [];
/** @type {RowData[]} */
this.rows = [];
Promise.all( [
apiQueryAllPages( sourceApi, this.namespace ),
apiQueryAllPages( targetApi, this.namespace ),
apiCargoQueryAll( targetApi )
] ).then( function ( data ) {
self.onDataFetch( data );
} );
}
/**
* @param {[ PageQueryResult[], PageQueryResult[], CargoQueryResult[] ]} data
*/
TranslationList.prototype.onDataFetch = function ( data ) {
var self = this;
this.sourcePages = data[ 0 ];
this.targetPages = data[ 1 ];
Promise.all( data[ 2 ].map( this.linkCargoTuple, this ) ).then( function ( rows ) {
rows = self.sourcePages.reduce( accUnlinkedSourcePage, rows );
rows = self.targetPages.reduce( accUnlinkedTargetPage, rows );
self.rows = rows;
self.fillTable();
} );
};
TranslationList.prototype.fillTable = function () {
var $table = this.$table,
$tbody = $table.children( 'tbody' ).empty(),
rows = this.rows;
for ( var i in rows ) {
var row = rows[ i ],
$tr = $( '<tr>' ).appendTo( $tbody ),
$targetTd = $( '<td>' ).appendTo( $tr ),
$lArrowTd = $( '<td>' ).appendTo( $tr ),
$statusTd = $( '<td>' ).appendTo( $tr ),
$rArrowTd = $( '<td>' ).appendTo( $tr ),
$sourceTd = $( '<td>' ).appendTo( $tr );
// TODO: Check if an existing function can be used instead.
if ( $table.hasClass( 'mw-collapsed' ) ) {
$tr.css( 'display', 'none' );
}
// Fills the source page cells
if ( row.source ) {
$rArrowTd.html( '←' );
$sourceTd.html(
'<a href="' + sourceWikiRoot + '/index.php?curid=' + row.source.pageid + '">' +
row.source.title + '</a>'
);
} else {
$tr.addClass( 'translation-list-nosource' );
$rArrowTd.css( 'color', 'grey' ).html( '⬾' );
}
// Fills the target page cells
if ( row.target ) {
$targetTd.html(
'<a href="' + targetWikiRoot + '/index.php?curid=' + row.target.pageid + '">' +
row.target.title + '</a>'
);
$lArrowTd.html( '→' );
} else {
$tr.addClass( 'translation-list-notarget' );
$lArrowTd.css( 'color', 'grey' ).html( '⥇' );
}
// If the source or target page is unlinked.
if ( !row.source || !row.target ) {
$statusTd.css( 'color', 'darkred' ).html( '☒' );
break;
}
// If the translation is up-to-date.
if ( row.oldRevision === row.newRevision ) {
$tr.addClass( 'translation-list-uptodate' );
$statusTd.css( 'color', 'green' ).html( '☑' );
break;
}
// If the translation is outdated.
$tr.addClass( 'translation-list-outdated' );
$targetTd.html(
'<a href="' + targetWikiRoot + '/index.php?curid=' + row.target.pageid +
'&action=edit">' + row.target.title + '</a>'
);
$statusTd.html(
'<a href="' + sourceWikiRoot + '/index.php?type=revision&diff=' + row.newRevision +
'&oldid=' + row.oldRevision + '" style="color: red">☒</a>'
);
}
};
/**
* @param {CargoQueryResult} cargoTuple
*/
TranslationList.prototype.linkCargoTuple = function ( cargoTuple ) {
/** @type {RowData} */
var row = {
source: null,
target: null,
oldRevision: +cargoTuple.revision,
newRevision: 0
};
var targetPageTitle = cargoTuple.page;
var targetPage = this.targetPages.find( function ( targetPage ) {
return targetPage.title === targetPageTitle;
} );
if ( !targetPage ) {
mw.log.warn( 'Missing page ("' + row.oldRevision + '") with translation template.' );
return row;
}
row.target = {
pageid: targetPage.pageid,
title: targetPage.title
};
return sourceApi.get( {
action: 'query',
prop: 'info',
revids: row.oldRevision
} ).then( function ( data ) {
/** @type {?{ [ key: string ]: PageQueryResult & { lastrevid: string } }} */
var pages = data.query.pages;
if ( !pages || pages[ '-1' ] ) {
mw.log.warn(
'Invalid revision ID ("' + row.oldRevision + '") from translation template ' +
'on page "' + row.target.title + '".'
);
return row;
}
for ( var i in pages ) {
var sourcePage = pages[ i ];
row.source = {
pageid: i,
title: sourcePage.title
};
row.newRevision = +sourcePage.lastrevid;
}
return row;
} );
};
/**
* @param {RowData[]} rows
* @param {PageQueryResult} sourcePage
*/
function accUnlinkedSourcePage( rows, sourcePage ) {
var pageid = sourcePage.pageid;
if ( rows.find( function ( row ) {
return row.source && row.source.pageid === pageid;
} ) ) {
rows.push( {
source: {
pageid: pageid,
title: sourcePage.title
},
target: null,
oldRevision: 0,
newRevision: 0
} );
}
return rows;
}
/**
* @param {RowData[]} rows
* @param {PageQueryResult} targetPage
*/
function accUnlinkedTargetPage( rows, targetPage ) {
var pageid = targetPage.pageid;
if ( rows.find( function ( row ) {
return row.target && row.target.pageid === pageid;
} ) ) {
rows.push( {
source: null,
target: {
pageid: pageid,
title: targetPage.title
},
oldRevision: 0,
newRevision: 0
} );
}
return rows;
}
/**
* Queries all pages from a specific namespace.
* @param {mwApi} api MediaWiki API.
* @param {number} namespace Namespace title.
* @returns The page array promise.
*/
function apiQueryAllPages( api, namespace ) {
var args = {
action: 'query',
list: 'allpages',
rawcontinue: true,
aplimit: 500,
apnamespace: namespace
};
return _apiQueryAllPages( api, args, [] );
}
/**
* @param {mwApi} api
* @param {*} args
* @param {PageQueryResult[]} storage
* @returns {PageQueryResult[] | JQuery.Promise<PageQueryResult[]>}
*/
function _apiQueryAllPages( api, args, storage ) {
return api.get( args ).then( function ( data ) {
storage = storage ? storage.concat( data.query.allpages ) : data.query.allpages;
if ( !data[ 'query-continue' ] ) {
return storage;
}
for ( var i in data[ 'query-continue' ] ) {
for ( var arg in data[ 'query-continue' ][ i ] ) {
args[ arg ] = data[ 'query-continue' ][ i ][ arg ];
}
}
return _apiQueryAllPages( api, args, storage );
} );
}
/**
* Queries all tuples from the maintenance Cargo table.
* @param {mwApi} api MediaWiki API.
* @returns The tuple array promise.
*/
function apiCargoQueryAll( api ) {
return api.get( {
action: 'cargoquery',
tables: 'maintenance',
fields: '_pageName=page,revision',
limit: 500
} ).then( getCargoDataTitles );
}
/**
* Gets the title objects from a Cargo query result.
* @param {{ cargoquery: { title: CargoQueryResult }[] }} data
*/
function getCargoDataTitles( data ) {
return data.cargoquery.map( getTitle );
}
/**
* Gets the title property of an object.
* @template T
* @param {{ title: T }} obj Object.
* @returns The title property of the given object.
*/
function getTitle( obj ) {
return obj.title;
}
} );